后缀数组倍增算法模版

来源:互联网 发布:网络约车有哪些平台 编辑:程序博客网 时间:2024/05/01 08:32

LINK : http://bbezxcy.iteye.com/blog/1403297


 首先献上模版

 

Cpp代码  收藏代码
  1. #include<iostream>  
  2. #include<cstdio>  
  3. #include<cstring>  
  4. using namespace std;  
  5. const int Max = 20001;  
  6.   
  7. int  num[Max];  
  8. int sa[Max], rank[Max], height[Max];  
  9. int wa[Max], wb[Max], wv[Max], wd[Max];  
  10.   
  11. int cmp(int *r, int a, int b, int l){  
  12.     return r[a] == r[b] && r[a+l] == r[b+l];  
  13. }  
  14.   
  15. void da(int *r, int n, int m){          //  倍增算法 r为待匹配数组  n为总长度 m为字符范围  
  16.     int i, j, p, *x = wa, *y = wb, *t;  
  17.     for(i = 0; i < m; i ++) wd[i] = 0;  
  18.     for(i = 0; i < n; i ++) wd[x[i]=r[i]] ++;  
  19.     for(i = 1; i < m; i ++) wd[i] += wd[i-1];  
  20.     for(i = n-1; i >= 0; i --) sa[-- wd[x[i]]] = i;  
  21.     for(j = 1, p = 1; p < n; j *= 2, m = p){  
  22.         for(p = 0, i = n-j; i < n; i ++) y[p ++] = i;  
  23.         for(i = 0; i < n; i ++) if(sa[i] >= j) y[p ++] = sa[i] - j;  
  24.         for(i = 0; i < n; i ++) wv[i] = x[y[i]];  
  25.         for(i = 0; i < m; i ++) wd[i] = 0;  
  26.         for(i = 0; i < n; i ++) wd[wv[i]] ++;  
  27.         for(i = 1; i < m; i ++) wd[i] += wd[i-1];  
  28.         for(i = n-1; i >= 0; i --) sa[-- wd[wv[i]]] = y[i];  
  29.         for(t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < n; i ++){  
  30.             x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p - 1: p ++;  
  31.         }  
  32.     }  
  33. }  
  34.   
  35. void calHeight(int *r, int n){           //  求height数组。  
  36.     int i, j, k = 0;  
  37.     for(i = 1; i <= n; i ++) rank[sa[i]] = i;  
  38.     for(i = 0; i < n; height[rank[i ++]] = k){  
  39.         for(k ? k -- : 0, j = sa[rank[i]-1]; r[i+k] == r[j+k]; k ++);  
  40.     }  
  41. }  
  42.   
  43. int main(){  
  44.     char str[Max];  
  45.     int i, m=30, ans,len;  
  46.     while(scanf("%s",str)!=EOF){  
  47.         len=strlen(str);  
  48.         for(i=0;i<=len;i++)num[i]=str[i]-'a'+1;  
  49.         num[len]=0;  
  50.         da(num, len + 1, m);  
  51.         calHeight(num, len);  
  52.         printf("num: \n");  
  53.         for(i=0;i<=len;i++){printf("%d ",num[i]);}printf("\n");  
  54.         printf("sa: \n");  
  55.         for(i=0;i<=len;i++){printf("%d ",sa[i]);}printf("\n");  
  56.         printf("rank: \n");  
  57.         for(i=0;i<=len;i++){printf("%d ",rank[i]);}printf("\n");  
  58.         printf("height: \n");  
  59.         for(i=0;i<=len;i++){printf("%d ",height[i]);}printf("\n");  
  60.     }  
  61.     return 0;  
  62. }  

 一直不清楚为什么要在最后要加上后缀0,希望有大神解释呃Orz。



 这里num[0~n-1]为有效值 就是输入的字符串稍稍转化而成的数组

       sa[1~~n]为有效值  sa[i]=a则代表排在第 i 位的是第a个后缀。  a属于[0~~n-1]

       rank[0~~n-1]是有效值  rank[i]=b则代表第 i 个后缀排在第b位   b属于[1~~n]

       height[2~~n]是有效值  height[i]=c 则代表排在第 i 位的后缀和排在第i-1的后缀的最长前缀长度是c。


0 0
原创粉丝点击