HDU3068 最长回文(manacher模板
给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.
回文就是正反读都是一样的字符串,如aba, abba等
回文就是正反读都是一样的字符串,如aba, abba等
Input输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S
两组case之间由空行隔开(该空行不用处理)
字符串长度len <= 110000Output每一行一个整数x,对应一组case,表示该组case的字符串中所包含的最长回文长度.
Sample Input
aaaa abab
Sample Output
4 3
1 #define maxn 1000010 2 #include <cstdio> 3 #include <iostream> 4 #include <algorithm> 5 #include <cstring> 6 7 using namespace std; 8 9 char str[maxn] ;//原字符串 10 char tmp[maxn << 1];//转换后的字符串 11 int Len[maxn << 1]; 12 13 //转换原始串 14 int INIT(char *st) 15 { 16 int i, len = strlen(st); 17 tmp[0] = '@';//字符串开头增加一个特殊字符,防止越界 18 for (i = 1; i <= 2 * len; i += 2) 19 { 20 tmp[i] = '#'; 21 tmp[i + 1] = st[i / 2]; 22 } 23 tmp[2 * len + 1] = '#'; 24 tmp[2 * len + 2] = '$';//字符串结尾加一个字符,防止越界 25 tmp[2 * len + 3] = 0; 26 return 2 * len + 1;//返回转换字符串的长度 27 } 28 //Manacher算法计算过程 29 int MANACHER(char *st, int len) 30 { 31 int mx = 0, ans = 0, po = 0;//mx即为当前计算回文串最右边字符的最大值 32 for (int i = 1; i <= len; i++) 33 { 34 if (mx > i) 35 Len[i] = min(mx - i, Len[2 * po - i]);//在Len[j]和mx-i中取个小 36 else 37 Len[i] = 1;//如果i>=mx,要从头开始匹配 38 while (st[i - Len[i]] == st[i + Len[i]]) 39 Len[i]++; 40 if (Len[i] + i > mx)//若新计算的回文串右端点位置大于mx,要更新po和mx的值 41 { 42 mx = Len[i] + i; 43 po = i; 44 } 45 ans = max(ans, Len[i]); 46 } 47 return ans - 1;//返回Len[i]中的最大值-1即为原串的最长回文子串额长度 48 } 49 50 51 int main() 52 { 53 while(cin>>str){ 54 int len = INIT(str); 55 cout<<MANACHER(tmp, len)<<endl; 56 57 } 58 }