后缀数组二倍增模板解析

原创 2015年07月09日 22:29:49

后缀数组模板解析

    自己的理解和分析 如有错误或不同的理解请指出。

    int cmp(int *r, int a, int b, int k)

    {

        return r[a] == r[b]&&r[a + k] == r[b + k];

    }

    void getsa(int *r, int *sa, int n, int m)

    {

        int i, j, p, *x = wa, *y = wb, *t;  

        for(i = 0;i < m;i++)

            wsf[i] = 0;

        for(i = 0;i < n;i++)

            wsf[x[i] = r[i]]++;

        for(i = 1;i < m;i++)

            wsf[i] += wsf[i - 1];

        for(i = n - 1;i >= 0;i--)

            sa[--wsf[x[i]]] = i;

      基基排序。(基数排序)

      X[i]数组记录的是一开始的r[i]的值。 

      Wsf[i]数组记录的是值为i和小于i的元素有几个。

      最后一个循环则是记录排第几的数的位置。

 

        j = 1;

        p = 1;

        for(;p < n;j *= 2, m = p)

        {

            for(p = 0, i = n - j;i < n;i++)

                y[p++] = i;

            for(i = 0;i < n;i++)

                 if(sa[i] >= j)

                     y[p++] = sa[i] - j;

      Y[i]记录的是排名为i的第二要素的第一要素位置。

      Sa[i]记录的是上一次排序的元素排名第i的元素的位置。

      因为是二倍增排序,j就是第二要素据第一要素的距离,所以n-j第一元素的第二元素都为零,所以排名直接从零开始。

      第二个for循环就是单纯的记录第二要素的排名。至于为什么sa[i]>=j是因为j前面的元素不肯能作为第二元素。

            for(i = 0;i < n;i++)

                wv[i] = x[y[i]];

            for(i = 0;i < m;i++)

                wsf[i] = 0;

            for(i = 0;i < n;i++)

                 wsf[wv[i]]++;

            for(i = 1;i < m;i++)

                 wsf[i] += wsf[i - 1];

            for(i = n - 1;i >= 0;i--)

                sa[--wsf[wv[i]]] = y[i];

    与一开始一样 是基基排序。至于第一个for循环则是根据第二元素进行了排序然后赋值。因为最后一个for循环是从后往前的所以先扫到的排名低,所以要构成一个新的数列。

    同样的 因为第一个for循环 所以最后一个for循环就是=y[i].因为y[i]表示的是第二元素排名第i位的第一元素的位置.sa[i]数组记录的是排名第i位的原数组的位置。

            t = x;

            x = y;

            y = t;

            x[sa[0]] = 0;

            for(i = 1, p = 1;i < n;i++)

                 x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1: p++;

        }

    }

    数组交换.

    因为一开始人为的加入了x[末尾+1] = 0;0肯定是排在第0位的,所以x[sa[0]] = 0;只是再加一遍而已。这里p 的值表示的是不同关键值得数量。

    void getheight(int *r, int n)

    {

        int i, j, k = 0;

        for(i = 1; i <= n;i++)

             rank[sa[i]] = i;

      求出rank数组,rank[i]的意思是位置为i的后缀的排名,与sa[i]数组正好互逆。

      for(i = 0; i < n;i++)

      {

            if(k)

                k--;

            else

                k = 0;

            j = sa[rank[i] - 1];

            while(r[i + k] == r[j + k])

                k++;

            height[rank[i]] = k;

        }

    }

      J是位置为i的后缀排名前一名的位置。如果这两个字符相等边加一。

                                  

                                                                                             2015.7.9 by Eson

后缀数组(倍增法)

后缀数组(Suffix Array):将某个字符串的所有后缀按字典序排序后得到的数组。 算法:朴素实现:直接将所有后缀进行排序,将n个长度为O(n)的字符串进行排序,时间复杂度O(n^2*logn);...
  • m0_37846371
  • m0_37846371
  • 2017年09月07日 23:33
  • 127

SA(后缀数组)——倍增法模板

倍增法原理:一步一步把n个后缀按照它们的前 2 ^ k 的字符排序。
  • Cold_Chair
  • Cold_Chair
  • 2017年03月17日 21:50
  • 242

后缀数组倍增法

那夜风,宫灯昏暗,小楼听雨灯辉摇梦
  • reverie_mjp
  • reverie_mjp
  • 2016年04月17日 22:04
  • 495

后缀数组——罗穗骞倍增算法代码详解

首先解释一下用到的几个数组。 数组sa:构造完成前表示关键字数组,下标表示名次,值表示关键字的首字符位置,值相同的时候名次根据在原串中相对位置的先后决定;构造完成后表示后缀数组,下标表示名次,值表示...
  • rockzh1993
  • rockzh1993
  • 2015年12月19日 10:28
  • 1899

后缀数组倍增算法代码及解释

最近在学习后缀数组
  • QWsin
  • QWsin
  • 2016年04月27日 15:01
  • 422

后缀数组倍增构造算法说解

算法:倍增 数据结构:后缀数组
  • Foliciatarier
  • Foliciatarier
  • 2017年03月10日 16:31
  • 101

实现后缀数组的倍增算法和DC3算法

/************************************************ 数据结构:后缀数组(Suffix_Array); 子串: 字符串S的子串r[i..j],i≤j,表...
  • Jarily
  • Jarily
  • 2013年03月22日 14:31
  • 3149

倍增法求LCA的模板

转载一发给自己看 http://blog.csdn.net/waitfor_/article/details/8070596 代码 /* 2^17=131072; ...
  • xl2015190026
  • xl2015190026
  • 2017年01月14日 18:31
  • 227

刘汝佳蓝书后缀数组模板解释及补全

相信很多初学后缀数组的ACMer在学习蓝书中的后缀数组部分遇到了一些障碍,可能像我一样看明白了P219 ——220的讲解和算法,百度了基数排序的方法,然后被卡在P221的代码上了,本文目的即分享我对这...
  • jijijix
  • jijijix
  • 2016年08月25日 23:37
  • 1595

后缀数组罗穗蹇模板(dc3)

#include #include #include #include #define maxn 1000003 #define F(x) ((x)/3+((x)%3==1?0:tb)) #defin...
  • u013665921
  • u013665921
  • 2014年10月14日 09:52
  • 1394
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:后缀数组二倍增模板解析
举报原因:
原因补充:

(最多只允许输入30个字)