• 后缀数组 (倍增法) 个人理解


      阅兵假期搞了后缀数组(倍增法),今天准备去Get DC3算法,但是回过头来看倍增法,竟然发现不少东西耶。扎扎决定要写一个总结帖。

      感觉其实倍增法中只要搞明白了每个数组都代表的什么意思,理解起来并不是很难,只是在排序的时候引入了一种崭新并且稳定的排序方法(一定要给想出这个算法的聚聚们狠狠的点个赞真是把数组用到了极致)。

      先介绍基数排序好辣,比如说有一串数字:73, 22, 93, 43, 55, 14, 28, 65, 39, 81

                第一步先对个位(第一关键字)排序,可得结果是:81, 22, 73, 93, 43, 14, 55, 65, 28, 39

                然后再按照十位(第二关键字)排序,最终得出:14, 22, 28, 39, 43, 55, 65, 73, 81, 93

      然后就是倍增法:先对每一个字符进行排序,然后再把排好序的子串再作为一个整体,然后相连的两个整体作为一个对象进行排序,只到最后文本串变为一个整体即可。

      重要的就是如何倍增排出顺序,我们在这之前先介绍一下算法中数组代表的含义:

            suffix[i]   以i为起始位置的后缀串
            rank[i]   以第i为字母开头的后缀串的排名
            sa[i]   排名为i后缀串的起始位置
            height[i]   suffix[sa[i-1]]与suffix[sa[i]]的公共前缀的长度

     1 //后缀数组(倍增法)
     2 
     3 int sa[maxn], rank[maxn], height[maxn];
     4 int t1[maxn], t2[maxn], r[maxn], c[maxn];
     5 bool cmp (int *str, int a, int b, int k)
     6 {
     7     //rank相邻的两个串,第一第二关键字都一样,rank一样
     8     return str[a]==str[b] && str[a+k]==str[b+k];
     9 }
    10 int da (int *str, int n, int m)
    11 {
    12     //文本串,文本串长度,文本串中最大的字符+1
    13     int *x = t1, *y = t2, i, j;
    14     n ++;
    15     //首次基数排序,对每位数字进行排序
    16     for (i=0; i<m; i++) c[i] = 0;
    17     for (i=0; i<n; i++) c[x[i] = str[i]] ++;
    18     for (i=1; i<m; i++) c[i] += c[i-1];
    19     for (i=n-1; i>=0; i--) sa[-- c[str[i]]] = i;
    20     for (j=1; j<=n; j*=2)
    21     {
    22         //用sa数组对第二关键字排序
    23         int p = 0;
    24         for (i=n-j; i<n; i++) y[p++] = i;  
    25         //[n-j,n)没有对应的第二关键字,故第二关键字排名最小
    26         for (i=0; i<n; i++) if (sa[i] >= j) y[p++] = sa[i] - j;
    27         //i为关键字排名,第二关键字起始位置在[1,j),不会有第一关键字
    28         //更新sa数组,y[i]  排名为i的第二关键字所对应第一关键字的起始位置
    29         for (i=0; i<m; i++) c[i] = 0;
    30         for (i=0; i<n; i++) c[x[y[i]]] ++;
    31         for (i=1; i<m; i++) c[i] += c[i-1];
    32         for (i=n-1; i>=0; i--) sa[-- c[x[y[i]]]] = y[i];
    33         //更新x数组,x[i] 起始位置为i的关键字1的排名
    34         swap (x, y);
    35         p = 1, x[sa[0]] = 0;
    36         for (i=1; i<n; i++)
    37             x[sa[i]] = cmp(y, sa[i-1], sa[i], j)?p-1:p++;
    38         if (p >= n)
    39             break;
    40         m = p;
    41     }
    42     //计算rank数组
    43     for (i=0; i<n; i++)
    44         rank[sa[i]] = i;
    45     //计算height数组
    46     n --;
    47     int k = 0;
    48     for (i=0; i<n; i++)
    49     {
    50         //枚举起点, height[名次]
    51         if (k)  k --;
    52         j = sa[rank[i]-1];
    53         while (str[i+k]==str[j+k])    k++;
    54         height[rank[i]] = k;
    55     }
    56 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    jQuery的deferred对象详解 jquery回调函数
    Table does not have the identity property. Cannot perform SET operation.
    SQLServer中merge函数用法详解
    jQuery事件命名空间多事件绑定自定义事件js 命名空间 javascript命名空间
    you have mixed tabs and spaces fix this
    java.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequest
    SQLServer 窗口函数
    TFS中查看我的所有签入迁出记录 TFS 怎么查看所有的修改
    日历控件My97DatePicker WdatePicker屏蔽 onchange的解决方法
    【Python】生成词云
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4789859.html
Copyright © 2020-2023  润新知