• 洛谷P3809 后缀数组模板


    题目:https://www.luogu.org/problemnew/show/P3809

    刚学了后缀数组,看人家手写演示了半天,大概明白了过程,但完全写不出来代码;

    于是借鉴了许多,不过都差不多,总算会写了;

    如何把想法实现出来很重要啊...

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int const maxn=1e6+5;
    int n,m,rk[maxn],tp[maxn],sa[maxn],a[maxn],num,tax[maxn];
    char s[maxn];
    void Rsort()
    {
        for(int i=0;i<=m;i++)tax[i]=0;
        for(int i=1;i<=n;i++)tax[rk[tp[i]]]++;
        for(int i=1;i<=m;i++)tax[i]+=tax[i-1];
        for(int i=n;i;i--)sa[tax[rk[tp[i]]]--]=tp[i];//tp是位置,rk是该位置第一关键字排名,tax存数量 
        //tp[i]是第二关键字从小到大进入,所以从大到小出来就可以使用前缀 
    }
    void work()
    {
        for(int i=1;i<=n;i++)rk[i]=a[i],tp[i]=i;
        Rsort();
        for(int k=1;k<=n;k<<=1)
        {
            num=0;
            for(int i=n-k+1;i<=n;i++)tp[++num]=i;//n-k以后的i后缀第二关键字是0,字典序最小 
            for(int i=1;i<=n;i++)//枚举排名(上一次的,也就是本次第一关键字) 
                if(sa[i]>k)tp[++num]=sa[i]-k;//排名从小到大,其所在位置如果大于k,则可以作为本次第二关键字
                //sa[i]-k 是位置,若上一次的第i名作为本次第二关键字,则所得后缀的位置在sa[i]-k 
            Rsort();
            swap(rk,tp);//tp存下上一次排名,也就是本次第一关键字的排名 
            rk[sa[1]]=1;
            num=1;
            for(int i=2;i<=n;i++)
                rk[sa[i]]=(tp[sa[i]]==tp[sa[i-1]]&&tp[sa[i]+k]==tp[sa[i-1]+k])?num:++num;
            //比较前后两半排名是否相同 
            if(num==n)break;
            m=num;//m是种类 
        }
    }
    int main()
    {
        cin>>s;
        n=strlen(s); m=122;
        for(int i=1;i<=n;i++)a[i]=s[i-1];
        work();
        for(int i=1;i<=n;i++)printf("%d ",sa[i]);
        return 0;
    }
  • 相关阅读:
    Web 服务器配置
    Web 浏览
    C++ Web 编程
    C++ 多线程
    C++ 信号处理
    C++ 预处理器
    C++ 模板
    C++ 命名空间
    C++ 动态内存
    C++ 异常处理
  • 原文地址:https://www.cnblogs.com/Zinn/p/9329820.html
Copyright © 2020-2023  润新知