• 后缀数组入门学习(1):倍增算法基础


    满心欢喜来了后缀数组,但是发现自己很懵……

    后缀数组倍增算法的板子并不长,但理解起来相对很困难。

    后缀的含义自然不用说了……为了简洁,我们设后缀i为从第i位开始的后缀。

    需要这样几个数组:

    char s[],存字符串(废话),int sa[](本体),xx[](中转数组,存rank),yy[](中转数组,存编号),c[](基排用)

    然后我们需要预备知识:基数排序

    具体理论就不说了,可以参考百度百科;

    形象一点:找了一堆桶,把每个数/字符放在对应的桶里,然后按桶的编号挨个取出来,排好,就是基数排序。

    在代码实现上c数组就是我们的桶,c[i]表示“字符值小于等于i的字符个数”

    而对于字符值恰好等于i的那个字符,它的排名就是c[i](由于它是小于等于i的最大一个字符),然后我们把c[i]-=1即可

    代码长这样:

    1 memset(c,0,sizeof(c));
    2 for(int i=0;i<n;i++)c[x[i]=s[i]]++;//这里是一开始初始化赋值的地方
    3 for(int i=1;i<m;i++)c[i]+=c[i-1];
    4 for(int i=n-1;~i;i--)sa[--c[x[i]]]=i;

    接下来,我们就可以介绍本体代码了:

    首先,我们对每个字符排序,这样我们会得到每个字符的排名。可能有同学有疑问,按照基排的话,相同字母的排名就不同了怎么办?后面我们还会有去重的部分,所以我们中转数组这样不重复的打也没事。在这之后,我们给每个后缀的前两个字符排序(没有第二个字符的按照0处理,0最小,以后也是这样操作)。这相当于给一些二元组排序。利用我们刚刚第一次给字母排序的结果,很容易实现这次排序(我们在从第二次开始每次排序后面都会进行一次去重)。

    这之后,我们对每个后缀的前4个字符排序。由于对于后缀i和后缀j,给他们的前4个字符排序相当于“比较i和j的前两个字符”和“比较i+2和j+2的前两个字符”,而我们已经给前两个字符排好序,所以这样就可以利用前面排序的结果来操作。

    不断这样操作,当每个后缀的排名都不同时,就可以跳出了。

    代码见下:

     1 char s[N];
     2 int sa[N],rank[N],xx[N],yy[N],c[N],n;
     3 inline void get_sa(int m)//m为最大的字符值
     4 {
     5     int *x=xx,*y=yy;
     6     memset(c,0,sizeof(c));
     7     for(int i=0;i<n;i++)c[x[i]=s[i]]++;
     8     for(int i=1;i<m;i++)c[i]+=c[i-1];
     9     for(int i=n-1;~i;i--)sa[--c[x[i]]]=i;
    10     for(int k=1,p=0;k<=n;k<<=1,p=0)
    11     {
    12         for(int i=n-k;i<n;i++)y[p++]=i;
    13         for(int i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k;
    14         memset(c,0,sizeof(c));
    15         for(int i=0;i<n;i++)c[x[y[i]]]++;
    16         for(int i=1;i<m;i++)c[i]+=c[i-1];
    17         for(int i=n-1;~i;i--)sa[--c[x[y[i]]]]=y[i];
    18         swap(x,y);
    19         p=1,x[sa[0]]=0;
    20         for(int i=1;i<n;i++)
    21             x[sa[i]]=(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k])?p-1:p++;
    22         if(p>=n-1)return;m=p;
    23     }
    24 }
  • 相关阅读:
    宋宝华: 文件读写(BIO)波澜壮阔的一生【转】
    内核工具 – Sparse 简介【转】
    【java】JSON.toJSONString 空对象也可以转化为JSON字符串
    Seata分布式事务简单使用
    Mixin 工作原理
    公链
    公链
    公链
    公链
    公链
  • 原文地址:https://www.cnblogs.com/LadyLex/p/7112103.html
Copyright © 2020-2023  润新知