求一个字符串的最长子串,Manacher算法是一种O(n)的算法,很给力!
s2[0] = '$',是避免在循环中对数组越界的检查。
模板题,没有什么好说的。Manacher算法本身确实是要好好理解体会的。
1 #define LOCAL 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 using namespace std; 7 8 const int maxn = 110000 + 20; 9 char s1[maxn], s2[maxn * 2]; 10 int p[maxn * 2]; 11 12 void init(char s1[], char s2[]) 13 { 14 s2[0] = '$', s2[1] = '#'; 15 int j = 2; 16 for(int i = 0; s1[i] != '\0'; ++i) 17 { 18 s2[j++] = s1[i]; 19 s2[j++] = '#'; 20 } 21 s2[j] = '\0'; 22 } 23 24 void manacher(char s[]) 25 { 26 int id, mx = 0; 27 p[0] = 0; 28 for(int i = 1; s[i] != '\0'; ++i) 29 { 30 if(mx > i) 31 p[i] = min(p[2*id-i], mx - i); 32 else 33 p[i] = 1; 34 while(s[i+p[i]] == s[i-p[i]]) 35 ++p[i]; 36 if(i + p[i] > mx) 37 { 38 mx = i + p[i]; 39 id = i; 40 } 41 } 42 } 43 44 void getans(void) 45 { 46 int ans = 0; 47 for(int i = 1; s2[i] != '\0'; ++i) 48 ans = max(ans, p[i] - 1); 49 printf("%d\n", ans); 50 } 51 52 int main(void) 53 { 54 #ifdef LOCAL 55 freopen("3068in.txt", "r", stdin); 56 #endif 57 58 while(scanf("%s", s1) != EOF) 59 { 60 init(s1, s2); 61 manacher(s2); 62 getans(); 63 } 64 return 0; 65 }