2565: 最长双回文串
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1377 Solved: 714
[Submit][Status][Discuss]
Description
顺序和逆序读起来完全一样的串叫做回文串。比如acbca是回文串,而abc不是(abc的顺序为“abc”,逆序为“cba”,不相同)。
输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串。
输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串。
Input
一行由小写英文字母组成的字符串S。
Output
一行一个整数,表示最长双回文子串的长度。
Sample Input
baacaabbacabb
Sample Output
12
利用回文树统计以i为结尾的最长回文串长度和以i为开始的最长回文串的长度
#include <iostream> #include <string.h> #include <stdlib.h> #include <algorithm> #include <math.h> #include <stdio.h> using namespace std; typedef long long int LL; const int maxn=1e5+5; char str[maxn]; struct Tree { int next[maxn][26]; int fail[maxn]; int len[maxn]; int s[maxn]; int last; int p; int n; int new_node(int x) { memset(next[p],0,sizeof(next[p])); len[p]=x; return p++; } void init() { p=0; new_node(0); new_node(-1); last=0;n=0; s[0]=-1; fail[0]=1; } int get_fail(int x) { while(s[n-len[x]-1]!=s[n]) x=fail[x]; return x; } int add(int x) { x-='a'; s[++n]=x; int cur=get_fail(last); if(!(last=next[cur][x])) { int now=new_node(len[cur]+2); fail[now]=next[get_fail(fail[cur])][x]; next[cur][x]=now; last=now; } return len[last]; } }tree; int s1[maxn]; int s2[maxn]; int main() { while(scanf("%s",str)!=EOF) { int len=strlen(str); tree.init(); memset(s1,0,sizeof(s1)); memset(s2,0,sizeof(s2)); for(int i=0;i<len;i++) { s1[i]=tree.add(str[i]); } tree.init(); for(int i=len-1;i>=0;i--) { s2[i]=tree.add(str[i]); } int ans=0; for(int i=0;i<len;i++) { ans=max(ans,s1[i]+s2[i+1]); } printf("%d ",ans); } return 0; }