描述
传送门:hdu-3068
给出一个只由小写英文字符a,b,c…y,z组成的字符串S,求S中最长回文子串的长度.
回文就是正反读都是一样的字符串,如aba, abba等
输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c…y,z组成的字符串S
两组case之间由空行隔开(该空行不用处理)。
字符串长度len <= 110000
Output
每一行一个整数x,对应一组case,表示该组case的字符串中所包含的最长回文长度.
Examples
思路
- len最大是1100000,暴力肯定会T,直接套用Manachar算法。
- Manachar算法时间复杂度为$O(N)$。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| #include<bits/stdc++.h> using namespace std; #define CRL(a) memset(a,0,sizeof(a)) #define INF 0xfffffff const int N=110005; char s[N<<1];int p[N<<1];
int Manachar() { CRL(p); int n=strlen(s+1),mx=0,ans=0,id=0; for(int i=n;i>=1;i--){ s[i<<1]=s[i]; s[i<<1|1]='*'; } s[1]='*'; n=n<<1|1;
for(int i=0;i<n;i++){ if(mx>i) p[i]=min(mx-i,p[2*id-i]); else p[i]=1; while(i-p[i]>0&&i+p[i]<=n&&s[i-p[i]]==s[i+p[i]]) p[i]++; if (p[i]+i>mx) {id=i; mx=p[i]+i;} } for(int i=1;i<=n;i++) if(p[i]-1>ans) ans=p[i]-1; return ans; } int main() { while(~scanf("%s",s+1)) cout<<Manachar()<<endl; return 0; }
|