Description:
给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.
回文就是正反读都是一样的字符串,如aba, abba等
回文就是正反读都是一样的字符串,如aba, abba等
Input:
输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S
两组case之间由空行隔开(该空行不用处理)
字符串长度len <= 110000
两组case之间由空行隔开(该空行不用处理)
字符串长度len <= 110000
Output:
每一行一个整数x,对应一组case,表示该组case的字符串中所包含的最长回文长度.
Sample Input:
aaaa
abab
Sample Output:
4
3
详解:O(n)回文子串(Manacher)算法 - as_ - 博客园 http://www.cnblogs.com/biyeymyhjob/archive/2012/10/04/2711527.html
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int N=1e6+10; char S[N], s[N]; int r[N], k; ///r数组中保存以i为中心的回文串的半径 int Manacher() ///求出字符串中最大回文串的长度 { int i, mx, id = 0, Max = 0; ///mx是以id为中心的回文串的边界 for (i = 2; i < k; i++) { r[i] = 1; mx = r[id]+id; if (mx > i) r[i] = min(r[2*id-i], mx-i); ///如果以id为中心的回文串边界大于i,则有两种情况,一种是以i为中心的回文串包含在id中,那么以i为中心的半径就是(2*id-i)的半径,因为该点是i关于id对称的点 ///第二种是没有完全包含在id中,那么我们只能确定mx-i是最小的半径,最终取两者最小值(这是一种线性关系) while (s[i-r[i]] == s[i+r[i]]) r[i]++; ///再求完半径的最小值之后剩下的部分还是要判断是否属于这个半径的 if (mx < r[i]+i) id = i; ///因为要找的是最大值,所以更新 Max = max(Max, r[i]-1); } return Max; } int main() { int i, ans; while (scanf("%s", S) != EOF) { memset(r, 0, sizeof(r)); k = 2; s[0] = '$'; s[1] = '#'; ///为了避免处理边界,s[0]置为特殊符号 for (i = 0; S[i] != '