• ural 1297 后缀数组 最长回文子串


    https://vjudge.net/problem/URAL-1297

    题意:

    给出一个字符串求最长回文子串

    代码:

    //论文题,把字符串反过来复制一遍到后边,中间用一个没出现的字符隔开,然后就是枚举当以i位置为中间位时的最长回文串
    //是多大,就是求这中间的heigh数组的最小值。用rmq预处理。枚举位置时分回文串长度是奇数还是偶数。
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int MAXN=3000;
    int sa[MAXN+9],ra[MAXN+9],he[MAXN+9],buc[MAXN+9],xx[MAXN+9],yy[MAXN+9],f[MAXN+9][30];
    int len,m;
    char s[MAXN+9];
    void get_suf()
    {
        int *x=xx,*y=yy;
        for(int i=0;i<m;i++) buc[i]=0;
        for(int i=0;i<len;i++) buc[x[i]=s[i]]++;
        for(int i=1;i<m;i++) buc[i]+=buc[i-1];
        for(int i=len-1;i>=0;i--) sa[--buc[x[i]]]=i;
        for(int k=1;k<=len;k<<=1){
            int p=0;
            for(int i=len-1;i>=len-k;i--) y[p++]=i;
            for(int i=0;i<len;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
            for(int i=0;i<m;i++) buc[i]=0;
            for(int i=0;i<len;i++) buc[x[y[i]]]++;
            for(int i=1;i<m;i++) buc[i]+=buc[i-1];
            for(int i=len-1;i>=0;i--) sa[--buc[x[y[i]]]]=y[i];
            swap(x,y);
            p=1;x[sa[0]]=0;
            for(int i=1;i<len;i++){
                if(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k])
                    x[sa[i]]=p-1;
                else x[sa[i]]=p++;
            }
            if(p>=len) break;
            m=p;
        }
        for(int i=0;i<len;i++) ra[sa[i]]=i;
        int k=0;
        for(int i=0;i<len;i++){
            if(ra[i]==0) { he[0]=0; continue; }
            if(k) k--;
            int j=sa[ra[i]-1];
            while(s[i+k]==s[j+k]&&i+k<len&&j+k<len) k++;
            he[ra[i]]=k;
        }
    }
    void rmq1(int n)
    {
        for(int i=0;i<n;i++)
            f[i][0]=he[i];
        for(int j=1;(1<<j)<n;j++){
            for(int i=0;i+(1<<j)-1<n;i++)
                f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
        }
    }
    int rmq2(int l,int r)
    {
        if(r<l) swap(r,l);
        l++;
        int k=0;
        while(1<<(k+1)<=r-l+1) k++;
        return min(f[l][k],f[r-(1<<k)+1][k]);
    }
    int main()
    {
        while(scanf("%s",s)==1){
            int x=strlen(s);
            s[x]='0';
            len=x+1;
            for(int i=x-1;i>=0;i--) s[len++]=s[i];
            m=200;
            get_suf();
            rmq1(len);
            int id=0,max_len=1;
            for(int i=0;i<x;i++){
                int tmp;
                if(i!=0){
                    tmp=rmq2(ra[i],ra[2*x-i+1]);
                    if(tmp*2>max_len){
                        max_len=tmp*2;
                        id=i-tmp;
                    }
                }
                if(i!=x&&i!=0){
                    tmp=rmq2(ra[i],ra[2*x-i]);
                    if(tmp*2-1>max_len){
                        max_len=tmp*2-1;
                        id=i-tmp+1;
                    }
                }
            }
            for(int i=id;i<id+max_len;i++) printf("%c",s[i]);
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    Java基础之集合框架(Collection接口和List接口)
    Management
    .NET实现多个不同有效时间Session方案思考
    C#操作MySql数据库帮助类(Dapper,T-Sql)
    MVC控制器传递多个实体类集合到视图的方案总结
    高德js API根据出行方式和出现策略由起始点经纬度实现路线规划
    c#QQ邮件编程学习(收发邮件)
    自定义tt文本模板实现MySql指数据库中生成实体类
    Socket客户端
    Socket服务端
  • 原文地址:https://www.cnblogs.com/--ZHIYUAN/p/7599117.html
Copyright © 2020-2023  润新知