最大回文字符串
问题描述:
求一段字符串中最大的回文子串,比如字符串c1 = 123456789aaabbbccccccbbbddd987654321,最大的回文子串就是bbbccccccbbb
问题解答:
之前使用后缀树来找过最长公共子串问题(可参考我之前的bloghttp://www.cnblogs.com/L-aho/articles/2444768.html),在这里同样可以利用上。需要做的就是再反向复制原有子串c2 = 123456789dddbbbccccccbbbaaa987654321,针对这个字符串同样建立一棵后缀树。使用qsort来对两棵后缀树进行排序操作,我们就能分别得到下面的结构:
1、对于两边的字符串再分别使用两个指针指向起始的位置
2、求出二者从起始字母开始有多少重合部分,并且再判断二者在原字符串中是否属于回文字符串,比如第二行的左边123456789和右边的123456789重合,但是在原字符串中并不是回文字符串,抛弃。
3、比较两边的大小,小的一边指针往下移动,继续2的操作,直到最后结束
下面为C代码描述:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXN 50000 int comlen(char* p, char* q) { int i = 0; while (*q && (*p++ == *q++)) { i++; } return i; } int cstring_cmp(const void *a, const void *b) { const char **ia = (const char **)a; const char **ib = (const char **)b; return strcmp(*ia, *ib); } int main() { char c[MAXN]; char* a[MAXN]; char ch; int n = 0; while ((ch = getchar()) != EOF) { a[n] = &c[n]; c[n++] = ch; } //相对于a的一个反向的后缀树 char* b[MAXN]; char c2[MAXN]; for (int i = 0; i < n - 1; i++) { c2[i] = c[n -2 - i]; b[i] = &c2[i]; } b[n - 1] = 0; qsort(a, n - 1, sizeof(char*), cstring_cmp); qsort(b, n - 1, sizeof(char*), cstring_cmp); int an = 0; int bn = 0; int ref = -1; int maxlen = 0; int maxi = 0; int maxib = 0; int len = 0; //启动 len = comlen(a[an], b[bn]); if ((an + len) == (strlen(b[bn]))) { maxlen = len; maxi = an; } ref = strcmp(a[an], b[bn]); if (ref == 1) { bn++; } else { an++; } while (an < n - 1 && bn < n - 1) { len = comlen(a[an], b[bn]); if ((maxlen < len) && ((n - strlen(a[an])) + len) == (strlen(b[bn]))) { maxlen = len; maxi = an; maxib = bn; } //继续比赛 ref = strcmp(a[an], b[bn]); if (ref == 1) { bn++; } else { an++; } } printf("maxlen:%d\tmax string:\t", maxlen); char ch_tmp; for (int i = 0; i < maxlen; i++) { ch_tmp = *(a[maxi] + i); printf("%c", ch_tmp); } printf("\n"); return 0; }