题解 CF30E 【Tricky and Clever Password】

y2823774827y

2019-10-14 15:53:37

Solution

该串分为$x+A+y+B+z+C$ $xyz$是来捣乱的,$A$与$C$对称,$B$长度为奇数,关于中心对称 - $B$可以用$manacher$做一下 - 观察$A,C$,直接在原串的基础上不好匹配,我们把原串翻过来,$C$所处的位置是前缀,可以用$kmp$做一下 >初赛rp++!! 代码有点不可看,只适合拍 ```cpp #include<bits/stdc++.h> typedef int LL; const LL maxn=1e6+9; LL n,ans,az,al; char s[maxn],s1[maxn],T[maxn]; LL hw[maxn],nxt[maxn],suf[maxn],sux[maxn],sua[maxn]; inline void Change1(){ for(LL i=1;i<=n;++i){ s1[i*2-1]=s[i]; s1[i*2]='#'; } } inline void Manacher(){ hw[1]=1; LL mid=1,Maxr(1); for(LL i=2,N=n<<1;i<=N;++i){ if(i<Maxr) hw[i]=std::min(hw[(mid<<1)-i],hw[mid]-(i-mid)); else hw[i]=1; while(s1[i-hw[i]]==s1[i+hw[i]]) ++hw[i]; if(i+hw[i]>Maxr){ Maxr=i+hw[i]; mid=i; } } for(LL i=3;i<=(n<<1);i+=2){ if(s1[i+hw[i]]=='#') hw[i]--; else hw[i]-=2; hw[(i>>1)+1]=hw[i]+1; } } inline void Change2(){ for(LL i=1,up=n>>1;i<=up;++i) T[i]=s[n+1-i],T[n+1-i]=s[i]; for(LL i=2,j=0;i<=n;++i){ while(T[j+1]!=T[i] && j) j=nxt[j]; if(T[j+1]==T[i]) ++j,nxt[i]=j; else nxt[i]=0; } for(LL i=1,j=0;i<=n;++i){ while(T[j+1]!=s[i] && j) j=nxt[j]; if(T[j+1]==s[i]) ++j,suf[i]=j; else suf[i]=0; } } int main(){ scanf("%s",s+1); n=strlen(s+1); Change1(); Manacher(); Change2(); for(LL i=1;i<=n;++i){ if(suf[i]>=sux[i-1]) sux[i]=suf[i],sua[i]=i; else sux[i]=sux[i-1],sua[i]=sua[i-1]; } for(LL i=1;i<=n;++i){ if(ans<hw[i]+(std::min((sux[i-(hw[i]>>1)-1]),n-(i+(hw[i]>>1)))<<1)){ ans=hw[i]+(std::min((sux[i-(hw[i]>>1)-1]),n-(i+(hw[i]>>1)))<<1); az=i; al=sua[i-(hw[i]>>1)-1]; } } if((n-(az+(hw[az]>>1))) && al && suf[al]){ puts("3"); LL len(std::min(suf[al],n-(az+(hw[az]>>1)))); printf("%d %d\n",al-len+1,len); printf("%d %d\n",az-(hw[az]>>1),hw[az]); printf("%d %d\n",n-len+1,len); }else{ puts("1"); printf("%d %d",az-(hw[az]>>1),hw[az]); } return 0; } ```