BZOJ 2565: 最长双回文串 [Manacher]
2565: 最长双回文串
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1842 Solved: 935
[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
一行一个整数,表示最长双回文子串的长度。
Manacher后处理每个#左右最长被以L R为中心的回文串覆盖
答案用R-L来更新
我迷之TLE了40min
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N=3e5+5; typedef long long ll; int n; char s[N],str[N]; int r[N]; void Manacher(char s[],int n){ int p=0,a; for(int i=1;i<=n;i++){ r[i]=i<p?min(p-i+1,r[2*a-i]):1; while(s[i-r[i]]==s[i+r[i]]) r[i]++; if(i+r[i]-1>p) p=i+r[i]-1,a=i; } } void iniStr(char str[],char s[]){ for(int i=1;i<=n;i++) s[(i<<1)-1]='#',s[i<<1]=str[i]; s[n<<1|1]='#'; s[0]='@';s[(n<<1)+2]='$'; } int l[N]; int main(){ freopen("in","r",stdin); scanf("%s",str+1); n=strlen(str+1); iniStr(str,s); Manacher(s,n<<1|1); n=n<<1|1; int now=1,ans=0; for(int i=1;i<=n;i++){ while(now+r[now]-1<i) now++; l[i]=now; } now=n; for(int i=n;i>=1;i--){ while(now-r[now]+1>i) now--; if(i&1) ans=max(ans,now-l[i]); } printf("%d",ans); }
Copyright:http://www.cnblogs.com/candy99/