後綴數組二倍增模板解析

後綴數組模板解析

    自己的理解和分析 如有錯誤或不同的理解請指出。

    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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章