• 后缀排序


    Tim正在自学《数据结构》,他刚刚学会如何比较两个字符串大小。书上是这么说的(和Pascal语言中的比较规则相同,学习过Pascal语言的同学可以跳过这段): 

    比较两个不同字符串s1=’p1p2p3…pN’和s2=’q1q2q3…qM’的大小,设N<=M。
    若s1是s2的前缀,则s1qi,且i最小;若pis2。
    Tim想通过练习熟练运用这个规则,于是打算出许多字符串,并将它们从小到大排序。可是Tim非常懒,随机写出 K个很长的字符串实在是太麻烦了。不过聪明的他想到了一个好办法,他写了一个很长的字符串,自言自语说,“我只要把这个字符串的所有后缀从小到大排序就可以了”。
    Input
    仅有一行,且是一个仅包含小写字母的字符串,长度K不超过10^5。
    Output
    有K行,每行一个数字,第i行的数字Pi表示所有后缀中,第i小的是由原字符串第Pi个字符引导的后缀。
    Sample Input
    mississippi
    Sample Output
    11
    8
    5
    2
    1
    10
    9
    7
    4
    6
    3

    Sol:

    sa[i]=j...排名第i的后缀是从原串中的第j个位置开始的

    rank[i]=j...原串中第i个位置开始的后缀,排名为j

    两者是个互逆的函数,整个程序就是两个数组倒来倒过

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #define maxn 210000
    #define ll long long
    #define fill(a,b) memset(a,b,sizeof(a))
    using namespace std;
    int Rank[maxn],sa[maxn],a[maxn],wr[maxn],rsort[maxn],y[maxn];
    char c[110000];
    inline bool cmp(int k1,int k2,int ln)
    {
    return wr[k1]==wr[k2]&&wr[k1+ln]==wr[k2+ln];
    }
    inline void get_sa(int n,int m)
    {
        int k,p,ln;
        memcpy(Rank,a,sizeof(Rank));  //将a数组copy给Rank 
        memset(rsort,0,sizeof(rsort));
        for(int i=1;i<=n;i++) //对于每个字符统计它的出现次数 
    	     rsort[Rank[i]]++;
        for(int i=1;i<=m;i++) //对于每个字符统计有多少个比它小 
    	    rsort[i]+=rsort[i-1];
        for(int i=n;i>=1;i--) 
    	     sa[rsort[Rank[i]]--]=i;
    	     //sa[i]=j,排在第i小的后缀串是从原字符串第j个位置开始的 
        ln=1; p=0;
        while (p<n)
        {
            k=0;
            for(int i=n-ln+1;i<=n;i++) 
    		     y[++k]=i;
            for(int i=1;i<=n;i++) 
    		    if(sa[i]>ln) y[++k]=sa[i]-ln;
            for(int i=1;i<=n;i++) 
    		     wr[i]=Rank[y[i]];
    		//rank[i]=j ,从i开始的后缀是第 j 名的(和 sa 互逆,是排名(值))
            memset(rsort,0,sizeof(rsort));
            for(int i=1;i<=n;i++) 
    		     rsort[wr[i]]++;
            for(int i=1;i<=m;i++) 
    		    rsort[i]+=rsort[i-1];
            for(int i=n;i>=1;i--) 
    		     sa[rsort[wr[i]]--]=y[i];
            for(int i=1;i<=n;i++) 
    		    wr[i]=Rank[i];
            p=1; 
    		Rank[sa[1]]=1;
            for(int i=2;i<=n;i++) 
            {
                if(!cmp(sa[i],sa[i-1],ln)) p++;
                Rank[sa[i]]=p;
            }
            m=p; 
    		ln*=2;
        }
        for(int i=1;i<=n;i++)
            printf("%d
    ",sa[i]);
    }
    int main(){
        scanf("%s",c+1);
        int n=strlen(c+1);
        for(int i=1;i<=n;i++) 
    	     a[i]=c[i];
        get_sa(n,300);
        return 0;
    }
    

      

  • 相关阅读:
    Jquery 跨域访问 Lightswitch OData Service
    BizTalk 2010/2013 EDI B2B项目实践(1)
    Moon转告给你一个比Log4net更好日志框架--TracerX Logger 及其对应的日志查看器
    转告大家关于依赖注入
    明月语言专家简介
    几个常见翻译引擎的不完全对比
    说说我在项目中为什么不用实体框架,如果说我在诋毁你所爱的EF,请进来.
    大话ASP.NET(第二篇,Angular结构篇--翻译)
    大话ASP.NET开发(第一章 html5+css3+解耦问题的探讨)
    Moon.Orm性能报告
  • 原文地址:https://www.cnblogs.com/cutemush/p/12331639.html
Copyright © 2020-2023  润新知