【BZOJ】【2565】最长双回文串
Manacher算法
找出一个最长子串S=X+Y,且X和Y都是回文串,求最长的长度是多少……
同时找两个串明显很难搞啊……但是我们可以先找到所有的回文串!在找回文串的同时我们可以预处理出来l[i]和r[i]分别表示从 i 这个位置开始向左/右最长的回文串有多长,那么我们枚举两个回文串的分割点更新答案即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /************************************************************** 2 Problem: 2565 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:80 ms 7 Memory:4496 kb 8 ****************************************************************/ 9 10 //BZOJ 2565 11 #include<cstdio> 12 #include<cstring> 13 #include<cstdlib> 14 #include<iostream> 15 #include<algorithm> 16 #define rep(i,n) for(int i=0;i<n;++i) 17 #define F(i,j,n) for(int i=j;i<=n;++i) 18 #define D(i,j,n) for(int i=j;i>=n;--i) 19 using namespace std; 20 typedef long long LL; 21 inline int getint(){ 22 int r=1,v=0; char ch=getchar(); 23 for(;!isdigit(ch);ch=getchar()) if(ch=='-')r=-1; 24 for(; isdigit(ch);ch=getchar()) v=v*10+ch-'0'; 25 return r*v; 26 } 27 const int N=1e5+10,INF=~0u>>2; 28 /*******************template********************/ 29 char s[N]; 30 int p[N<<1],a[N<<1],l[N<<1],r[N<<1],n; 31 int main(){ 32 scanf("%s",s); 33 n=strlen(s); 34 F(i,1,n) a[i<<1]=s[i-1]; 35 n=n<<1|1; 36 37 int id=0,mx=0; 38 F(i,1,n){ 39 if (mx>i) p[i]=min(p[2*id-i],mx-i); 40 while(i-p[i]-1>0 && i+p[i]+1<=n && a[i-p[i]-1]==a[i+p[i]+1]){ 41 p[i]++; 42 l[i+p[i]]=max(l[i+p[i]],p[i]); 43 r[i-p[i]]=max(r[i-p[i]],p[i]); 44 } 45 if (p[i]+i>mx) mx=p[i]+i,id=i; 46 l[i+p[i]]=max(l[i+p[i]],p[i]); 47 r[i-p[i]]=max(r[i-p[i]],p[i]); 48 } 49 /* 50 F(i,1,n) printf("%c ",a[i]!=0?a[i]:'#'); puts(""); 51 F(i,1,n) printf("%d ",p[i]); puts(""); 52 F(i,1,n) printf("%d ",l[i]); puts(""); 53 F(i,1,n) printf("%d ",r[i]); puts(""); 54 */ 55 int ans=0; 56 F(i,1,n) if(l[i]+r[i]>ans) ans=l[i]+r[i]; 57 printf("%d\n",ans); 58 return 0; 59 }