2342: [Shoi2011]双倍回文
看了好长时间,太差了;
设(R[k])为以(k)为中心的最长回文串,(x)为(ww^Rww^R)对称轴,(y)为右半部分(ww^R)对称轴;
(ch[x])与(ch[y])一定为特殊字符,所以一定满足(R[x]>=2(y-x)),(R[y]>=y-x);
即(x+R[x]/2>=y),(x>=y-R[y]);
所以把(y)按(y-R[y])排序,枚举(x),把符合条件的(y)扔到(set)里(upper)_(bound)一下就行了;
AC GET☆DAZE
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define N 1000039
#define mod 20070831
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
int n,m,R[N],stp[N],ans;
char ch[N],rea[N];
set<int> pos;
set<int>::iterator th;
int force(int &id,int &mx,int r)
{
while(r<m)
{
if(rea[(id<<1)-r]!=rea[r]) break;
R[id]++,mx=r++;
}
}
void manacher()
{
int id=1,mx=1;
for(int a=1,b;mx<m && a<m;a++)
{
if(a>=mx) force(id=a,mx,a+1);
else
{
b=(id<<1)-a;
if(R[b]<mx-a) R[a]=R[b];
else
{
R[a]=mx-a;
force(id=a,mx,mx+1);
}
}
}
}
bool cmp(int i,int j)
{
return i-R[i]<j-R[j];
}
int main()
{
scanf("%d",&n);
scanf(" %s",&ch);
rea[0]='3',rea[m=2*n+2]='9';
for(int a=1;a<m;a++)
{
if(a&1) rea[a]='#';
else rea[a]=ch[(a>>1)-1];
stp[a]=a;
}
manacher();
sort(stp+1,stp+m,cmp);
for(int a=1,b=1;a<m;a+=2)
{
while(b<m && stp[b]-R[stp[b]]<=a)
{
if(stp[b]&1) pos.insert(stp[b]);
b++;
}
th=pos.upper_bound(a+R[a]/2);
if(th!=pos.begin())
{
th--;
ans=max(ans,2*(*th-a));
}
}
printf("%d",ans);
return 0;
}