• poj3693 Maximum repetition substring(后缀数组+ST表)


    http://poj.org/problem?id=3693

    这题要求在这道题https://www.cnblogs.com/TheRoadToTheGold/p/15141477.html的基础上输出字典序最小的解

    这是在上题的基础上的题解

    因为在计算最大重复次数的时候,会从分割点往前跳几个字符,得到一个重复子串的起点

    所以我输出解的时候,直接拿这个起点的rank作比较了

    这是不对的

    因为位置靠前不一定字典序小

    正确做法是记录所有重复次数相同的循环节长度

    然后按sa依次找

    #include<cmath>
    #include<cstdio>
    #include<cstring> 
    #include<algorithm>
    
    using namespace std;
    
    #define N 100005
    
    char ch[N];
    int n,k,a[N],v[N],p,q,sa[2][N],rk[2][N],h[N];
    
    int f[N][20];
    
    int may[N],tot;
    
    void mul(int *sa,int *rk,int *SA,int *RK)
    {
        for(int i=1;i<=n;i++) v[rk[sa[i]]]=i;
        for(int i=n;i;i--)
            if(sa[i]>k) 
                SA[v[rk[sa[i]-k]]--]=sa[i]-k;
        for(int i=n-k+1;i<=n;i++) 
            SA[v[rk[i]]--]=i;
        for(int i=1;i<=n;i++) 
            RK[SA[i]]=RK[SA[i-1]]+(rk[SA[i]]!=rk[SA[i-1]]||rk[SA[i]+k]!=rk[SA[i-1]+k]);
    }
    void presa()
    {
        p=0;
        q=1;
        for(int i=1;i<=26;++i) v[i]=0;
        for(int i=1;i<=n;i++) v[a[i]]++;
        for(int i=1;i<=26;i++) v[i]+=v[i-1];
        for(int i=1;i<=n;i++) 
            sa[p][v[a[i]]--]=i;
        for(int i=1;i<=n;i++) 
            rk[p][sa[p][i]]=rk[p][sa[p][i-1]]+(a[sa[p][i-1]]!=a[sa[p][i]]);
        for(k=1;k<n;k<<=1,swap(p,q))
            mul(sa[p],rk[p],sa[q],rk[q]);
        for(int i=1,k=0;i<=n;i++)
        {
            int j=sa[p][rk[p][i]-1];
            while(a[i+k]==a[j+k]) k++;
            h[rk[p][i]]=k;if(k) k--;
        }
    }
    
    void prest()
    {
        for(int i=2;i<=n;++i) f[i][0]=h[i];
        for(int i=1;1<<i<=n;++i)
            for(int j=2;j+(1<<i)-1<=n;++j)
                f[j][i]=min(f[j][i-1],f[j+(1<<i-1)][i-1]); 
    }
    
    int getlcp(int s,int t)
    {
        if(t>n) return 0;
        s=rk[p][s];
        t=rk[p][t];
        if(s<t) ++s;
        else 
        {
            swap(s,t);
            ++s;
        }
        int l=t-s+1;
        int m=log((double)l)/log((double)2);
        return min(f[s][m],f[t-(1<<m)+1][m]);
    }
    
    void solve()
    {
        int rep=1,sum,lcp,tmp,be,ll=1;
        prest();
        tot=0;
        for(int i=1;i<n;++i)
        {
            for(int j=1;j+i<=n;j+=i)
            {
                lcp=getlcp(j,j+i);
                sum=lcp/i+1;
                tmp=lcp%i;
                if(tmp)
                {
                    if(j-(i-tmp)>0)
                    {
                        lcp=getlcp(j-(i-tmp),j+i-(i-tmp));
                        if(lcp>=i) ++sum;
                    }
                }
                if(sum>rep)
                {
                    rep=sum;
                    ll=i;
                    may[tot=1]=i;
                }
                else if(sum==rep) may[++tot]=i;
            }
        }
        int L=rep*ll;
        for(int i=1;i<=n;++i)
        {
            for(int j=1;j<=tot;++j)
                if(getlcp(sa[p][i],sa[p][i]+may[j])>=(rep-1)*may[j])  
                {
                    be=sa[p][i];
                    for(int i=0;i<L;++i) printf("%c",ch[be+i]);
                    printf("
    "); 
                    return;
                }
        }
    }
    
    int main()
    {
        int T=0;
        while(1)
        {
            scanf("%s",ch+1);
            if(ch[1]=='#') return 0;
            printf("Case %d: ",++T);
            n=strlen(ch+1);
            for(int i=1;i<=n;i++) a[i]=ch[i]-'a'+1;
            presa();
            solve();
        }
    }
    作者:xxy
    本文版权归作者和博客园共有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。
  • 相关阅读:
    WindowsServer 2016激活
    selenium浏览器复用与原理分析
    react脚手架: 配置代理
    网络请求方式
    Java: Excel导入导出
    react 组件通信方式
    react: reactrouterdom
    react: 高阶函数及函数柯里化
    react: 事件处理
    react: 生命周期
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/15141492.html
Copyright © 2020-2023  润新知