最長迴文
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5319 Accepted Submission(s): 1815
Problem Description給出一個只由小寫英文字元a,b,c...y,z組成的字串S,求S中最長迴文串的長度.
迴文就是正反讀都是一樣的字串,如aba, abba等
Input輸入有多組case,不超過120組,每組輸入為一行小寫英文字元a,b,c...y,z組成的字串S
兩組case之間由空行隔開(該空行不用處理)
字串長度len <= 110000
Output每一行一個整數x,對應一組case,表示該組case的字串中所包含的最長迴文長度.
Sample Input
aaaaabab
Sample Output
43
Source2009 Multi-University Training Contest 16 - Host
by NIT
Recommendlcy 這個題目我是參考這篇部落格寫的!http://www.cnblogs.com/chenlie/archive/2011/05/30/2063100.html這個擴充的KMP本來就不是怎麼好理解,花了半天時間把擴充的KMP搞懂了,想應用一下,沒想到想用他求一個最長迴文字串都這麼困難,表示這個演算法不好理解啊擴充KMP演算法可以看我轉的這篇部落格http://chenhongyu940407.blog.163.com/blog/static/20500925420136251431685/講的非常詳細,思路非常清晰擴充KMP的最佳化思路和KMP基本上是一樣的就是計算過的不再計算!
#include <iostream>#include <cstdio>#include <string>#include <cstring>using namespace std;#define MAX 110010int next1[MAX];int next2[MAX];int next[MAX];int ans;char a[MAX];char b[MAX];int getNext1(int n){ int i=0,j=0,k=0,p=0,a=0,l=0; next[0]=n; while(j+1 < n && b[j+1]==b[j]) j++; next[1]=j; a=1; for(i=2;i<n;i++) { p=a+next[a]-1; l=next[i-a]; if(i+l <= p) next[i]=l; else { j=p-i+1; if(j<0) j=0; while(i+j < n && b[j]==b[i+j]) j++; next[i]=j; a=i; } } return 0;}void getNext2(char *s, int *nexts, int n, int m){ getNext1(m); int i, j, k; j = 0; k = 0; while (s[j] == b[j])j++; nexts[0] = j; for (i = 1; i < n; i++) { if (next[i-k] + i < nexts[k] + k) nexts[i] = next[i-k]; else { j = nexts[k] + k - i; if (j < 0) j = 0; while (i + j < n && s[i+j] == b[j])j++; nexts[i] = j; k = i; } }}void res(char *s, int n){ char st; int len = (n>>1); for (int i = 0; i < len; i++) { st = s[i]; s[i] = s[n-i-1]; s[n-i-1] = st; }}void find(char *s, int n){ if (ans >= n || n < 2)return; int i, k, x; int mid; mid = (n>>1); for (i = mid; i < n; i++)b[i-mid] = s[i]; b[i-mid] = 0; res(s, n); getNext2(s, next1, n, i-mid); res(s, n); for (i = 0; i < mid; i++) b[i] = s[mid-i-1]; b[i] = 0; getNext2(s, next2, n, mid); next1[n] = next2[n] = 0; for (i = 0; i < mid; i++) { if (next2[i] >= mid - i) { x = mid - i + 2 * next1[n-i]; if (ans < x)ans = x; } } for (i = mid; i < n; i++) { if (next1[n-i] >= i - mid) { x = i - mid + 2*next2[i]; if (ans < x) ans = x; } } find(s, mid); find(s+mid, n-mid);}int main(){ int n; while (scanf("%s", a) != EOF) { n = strlen(a); ans = 1; find(a, n); printf("%d\n", ans); } return 0;}