[BZOJ2341][Shoi2011]雙倍迴文 manacher+std::set
阿新 • • 發佈:2019-01-12
發現雙倍迴文串一定是中心是#
的迴文串。
所以考慮列舉#
點。發現以\(i\)為中心的雙倍迴文的左半部分是個迴文串,其中心一定位於\(i-\frac{pal[i]-1}2\)到\(i-1\)之間,而且越遠越好。所以我們用一個\(set\)來存一下目前為止迴文右端點\(\geq i\)的點,然後在\(set\)中找到大於等於\(i-\frac{pal[i]-1}2\)的最小值即可。
#include<bits/stdc++.h> using namespace std; #define fec(i,x,y) (int i=head[x],y=g[i].to;i;i=g[i].ne,y=g[i].to) #define dbg(...) fprintf(stderr,__VA_ARGS__) #define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout) #define isin(x,S) (((S)>>((x)-1))&1) #define fi first #define se second #define pb push_back template<typename I>inline void read(I&x){int f=0,c;while(!isdigit(c=getchar()))c=='-'?f=1:0;x=c&15;while(isdigit(c=getchar()))x=(x<<1)+(x<<3)+(c&15);f?x=-x:0;} template<typename A,typename B>inline char SMAX(A&a,const B&b){return a<b?a=b,1:0;} template<typename A,typename B>inline char SMIN(A&a,const B&b){return a>b?a=b,1:0;} typedef long long ll;typedef unsigned long long ull;typedef pair<int,int>pii; const int N=500000+7; int n,pal[N<<1],ans;char a[N],s[N<<1]; inline void Manacher(){ int p=0,pos=0; for(int i=1;i<=n;++i){ if(p>i)pal[i]=min(p-i+1,pal[(pos<<1)-i]);else pal[i]=1; while(s[i+pal[i]]==s[i-pal[i]])++pal[i]; if(SMAX(p,i+pal[i]-1))pos=i; } } set<int>t; vector<int>p[N<<1]; int main(){ #ifdef hzhkk freopen("hkk.in","r",stdin); #endif scanf("%d%s",&n,a+1); s[0]=s[1]='#'; for(int i=1;i<=n;++i)s[i<<1]=a[i],s[i<<1|1]='#'; n=n<<1|1; Manacher(); for(int i=1;i<=n;i+=2){ t.insert(i); if(i+pal[i]-1<=n)p[i+pal[i]-1].pb(i); if(i&1)SMAX(ans,(i-*t.lower_bound(i-(pal[i]-1)/2))*2); for(vector<int>::iterator j=p[i].begin();j!=p[i].end();++j)t.erase(*j); for(int i=1;i<=n;++i) } printf("%d\n",ans); }