hdu 3068 最长回文(manacher&最长回文子串)
最长回文
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 7317 Accepted Submission(s): 2500
Problem 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
Source
Recommend
题目:
中文见上。
思路:
manacher裸题。
主要是练习下。
manacher算法解说见here
思路主要是先给字符串加上隔离符。把回文串长度奇偶同一为求奇数回文长度。求出以每一个字符为中心字符的最大回文长度。后面的结果利用前面的结果。
p[i]-1为原回文串的长度。
具体见代码:
#include<iostream> #include<string.h> #include<stdio.h> using namespace std; const int INF=0x3f3f3f3f; const int maxn=111000; int p[maxn<<1],len; char buf[maxn],st[maxn<<1]; void init() { int i; len=strlen(buf); st[0]='$',st[1]='#'; for(i=0;i<len;i++) st[2*i+2]=buf[i],st[2*i+3]='#'; len=2*len+2; } void manacher() { int i,id,mx=0; for(i=1;i<len;i++) { p[i]=mx>i?min(mx-i,p[2*id-i]):1; while(st[i+p[i]]==st[i-p[i]])//不用操心越界。由于st[0]='$' p[i]++; if(i+p[i]>mx) mx=i+p[i],id=i; } } int main() { int i,ans; while(~scanf("%s",buf)) { ans=1; init(); manacher(); for(i=2;i<len;i++) ans=max(ans,p[i]); printf("%d\n",ans-1); } return 0; }