题意:就是给你一个字符串,然后求出他的最大回文串,然后打印字符串
思路:(这道题其实是可以用马拉车算法的而且复杂度很优秀 On的)但这里用的是后缀数组的解法,我们把一个串reverse翻转贴在后面,然后就是枚举中点,然后向两边扩展的,向两边扩展是可以用lcp做的,(NOI 2016中也用到了类似了方法)然后就可以 愉快地搬运了(ps:中间出了一点bug,找了很久才找到)
AC代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; LL read() { LL x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const int maxn=1e4+7; char s[maxn]; int T,n,Log[maxn],l,r,f[maxn],g[maxn]; void init_suffix() { for(int i=2;i<maxn;i++)Log[i]=Log[i>>1]+1; } struct SuffixArray { char s[maxn*2]; int sa[maxn*2],rk[maxn*2],height[maxn*2],tmp[maxn*2],cnt[maxn*2],f[15][maxn*2],len; inline void init() { for(int i=0;i<len*2+5;i++)s[i]=0; } inline void suffix(int m) { int i,j,k,len1=len+1;; for(i=0;i<len1*2+5;i++)rk[i]=sa[i]=height[i]=tmp[i]=0; for(i=0;i<m;i++)cnt[i]=0; for(i=0;i<len1;i++)cnt[rk[i]=s[i]]++; for(i=1;i<m;i++)cnt[i]+=cnt[i-1]; for(i=0;i<len1;i++)sa[--cnt[rk[i]]]=i; for(k=1;k<=len1;k<<=1){ for(i=0;i<len1;i++){ j=sa[i]-k; if(j<0)j+=len1; tmp[cnt[rk[j]]++]=j; } sa[tmp[cnt[0]=0]]=j=0; for(i=1;i<len1;i++){ if(rk[tmp[i]]!=rk[tmp[i-1]]||rk[tmp[i]+k]!=rk[tmp[i-1]+k])cnt[++j]=i; sa[tmp[i]]=j; } memcpy(rk,sa,len1*sizeof(int)); memcpy(sa,tmp,len1*sizeof(int)); if(j>=len1-1)break; } // for(j=rk[height[i=k=0]=0];i<=len;i++,k++){ // while(~k&&s[i]!=s[sa[j-1]+k])height[j]=k--,j=rk[sa[j]+1]; // } k=0; for(i=0;i<=len;i++) rk[sa[i]]=i; for(i=0;i<len;i++) { if(k) k--; j=sa[rk[i]-1]; while(s[j+k]==s[i+k]) k++; height[rk[i]]=k; } } inline void build() { int i,j; for(i=1;i<=len;i++)f[0][i]=height[i]; for(j=1;j<15;j++){ for(i=1;i+(1<<j-1)<=len;i++){ f[j][i]=min(f[j-1][i],f[j-1][i+(1<<j-1)]); } } } inline int ask(int x,int y) { int k=Log[y-x+1]; return min(f[k][x],f[k][y-(1<<k)+1]); } inline int lcp(int x,int y) { x=rk[x],y=rk[y]; if(x>y)swap(x,y); return ask(x+1,y); } }A; inline int lcp(int x,int y){return A.lcp(x-1,y-1);} int main() { init_suffix(); while(~scanf("%s",s)){ int n=strlen(s); A.len=2*n+2; A.init(); for(int i=0;i<n;i++){ A.s[i]=s[i]; } A.s[n]='#'; for(int i=n+1,j=n-1;i<2*n+1;i++,j--){ A.s[i]=s[j]; } A.s[2*n+1]='