URAL 1297

来源:互联网 发布:领航者炒股软件 编辑:程序博客网 时间:2024/06/05 19:07

后缀数组求最长回文串

#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>using namespace std;#define MAXN 2010int dp[2010][30];char r[MAXN],rr[MAXN];int sa[MAXN];int wa[MAXN],wb[MAXN],wv[MAXN],ws[MAXN];int height[MAXN],rk[MAXN];inline bool cmp(int *r,int a,int b,int len){    return r[a]==r[b]&&r[a+len]==r[b+len];}void SA(int n,int m){    int i,j,p,*x=wa,*y=wb,*t;    for(i=0;i<m;i++)        ws[i]=0;    for(i=0;i<n;i++)        ws[x[i]=r[i]]++;    for(i=1;i<m;i++)        ws[i]+=ws[i-1];    for(i=n-1;i>=0;i--)        sa[--ws[x[i]]]=i;    for(j=p=1;p<n;j<<=1,m=p){        for(p=0,i=n-j;i<n;i++)            y[p++]=i;        for(i=0;i<n;i++){            if(sa[i]>=j)                y[p++]=sa[i]-j;        }        for(i=0;i<m;i++)            ws[i]=0;        for(i=0;i<n;i++)            ws[wv[i]=x[y[i]]]++;        for(i=1;i<m;i++)            ws[i]+=ws[i-1];        for(i=n-1;i>=0;i--)            sa[--ws[wv[i]]]=y[i];        for(t=x,x=y,y=t,x[sa[0]]=0,p=i=1;i<n;i++)            x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;    }}void Height(int n){    int i,j,k=0;    for(i=0;i<=n;i++)    //这里sa[0]为‘\0’开始的子串        rk[sa[i]]=i;    for(i=0;i<n;height[rk[i++]]=k)        for(k?k--:0,j=sa[rk[i]-1];r[i+k]==r[j+k];k++);}int init(){    int i,j,len;    memset(height,0,sizeof(height));    len=strlen(rr);    for(i=0;i<len;i++)        r[i]=rr[i];    r[i]='$';    for(j=0;j<len;j++)        r[j+len+1]=r[len-1-j];    r[j+len+1]='\0';    return len*2+1;}void st(int n){    int i,j,p,q;    for(i=1;i<=n;i++)        dp[i][0]=i;    for(j=1;j<=(int)(log((double)n)/log(2.0));j++)        for(i=1;i+(1<<j)-1<=n;i++){            p=height[dp[i][j-1]];            q=height[dp[i+(1<<(j-1))][j-1]];            if(p>q)                dp[i][j]=dp[i+(1<<(j-1))][j-1];            else                dp[i][j]=dp[i][j-1];        }}int RMQ_MIN(int i,int j){    int tem;    if(i>j){        tem=i;        i=j;        j=tem;    }    i++;           //交换后小的要加一    int k=(int)(log((double)(j-i+1))/log(2.0));    return min(height[dp[i][k]],height[dp[j-(1<<k)+1][k]]);}void solve(int n){    int i,j,ans=0,s;    st(n);    for(i=0;i<n/2;i++){        j=RMQ_MIN(rk[i],rk[n-1-i]);        if(j*2-1>ans){            ans=j*2-1;            s=i-j+1;        }        j=RMQ_MIN(rk[i],rk[n-i]);        if(j*2>ans){            ans=j*2;            s=i-j;        }    }    for(i=s;i<s+ans;i++)        printf("%c",rr[i]);    printf("\n");}int main(){    int i,j,n;    scanf("%s",rr);    n=init();    SA(n+1,130);    Height(n);    solve(n);}



原创粉丝点击