后缀数组 求长度不小于k的公共子串的个数

代码:

 

  1 #include <stdio.h>
  2 #include <string.h>
  3 
  4 const int maxn = 200011;
  5 int len, len1;
  6 int wa[maxn], wb[maxn], wv[maxn], wd[maxn], sa[maxn];
  7 int lcp[maxn], r[maxn], rank[maxn], height[maxn];
  8 
  9 int cmp(int *r, int a, int b, int l){
 10     return r[a] == r[b] && r[a+l] == r[b+l];
 11 }
 12 
 13 void da(int *r, int n, int m){
 14     int i, j, p, *x=wa, *y=wb, *t;
 15     for(i = 0; i < m; i++) wd[i] = 0;
 16     for(i = 0; i < n; i++) wd[x[i] = r[i]]++;
 17     for(i = 1; i < m; i++) wd[i] += wd[i-1];
 18     for(i = n-1; i >= 0; i--) sa[--wd[x[i]]] = i;
 19     for(j = 1, p = 1; p < n; j *= 2, m = p){
 20         for(p = 0, i = n-j; i < n; i++) y[p++] = i;
 21         for(i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i]-j;
 22         for(i = 0; i < n; i++) wv[i] = x[y[i]];
 23         for(i = 0; i < m; i++) wd[i] = 0;
 24         for(i = 0; i < n; i++) wd[wv[i]]++;
 25         for(i = 1; i < m; i++) wd[i] += wd[i-1];
 26         for(i = n-1; i >= 0; i --) sa[--wd[wv[i]]] = y[i];
 27         for(t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < n; i++){
 28             x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p-1: p++;
 29         }
 30     }
 31 }
 32 
 33 void calHeight(int *r, int n){
 34     int i, j, k = 0;
 35     for(i = 1; i <= n; i++) rank[sa[i]] = i;
 36     for(i = 0; i < n; height[rank[i++]] = k){
 37         for(k ? k-- : 0, j = sa[rank[i]-1]; r[i+k] == r[j+k]; k++);
 38     }
 39 }
 40 
 41 int main(){
 42     int k;
 43     char str1[maxn], str2[maxn];
 44     while(~scanf("%d", &k)){
 45         if(k==0) break;
 46         scanf("%s%s",str1, str2);
 47         len1 = strlen(str1);
 48         len = strlen(str2);
 49         for(int i = 0; i < len1; i++){
 50             r[i] = str1[i];
 51         }
 52         r[len1] = '$';
 53         for(int i = 0; i < len; i++){
 54             r[i+len1+1] = str2[i];
 55         }
 56         len += len1+1;
 57         r[len] = 0;
 58         da(r, len+1, 150);
 59         calHeight(r, len);
 60         long long res = 0, sum;
 61         int head, tail;
 62         for(int i = 1; i <= len; i++){
 63             if(height[i] < k){
 64                 sum = 0;
 65                 head = tail = maxn;
 66             }
 67             else{
 68                 for(int j = head; j < tail; j++){
 69                     if(lcp[j] > height[i]){
 70                         sum -= lcp[j]-height[i];
 71                         lcp[j] = height[i];
 72                     }
 73                     else break;
 74                 }
 75                 if(sa[i-1] > len1){
 76                     lcp[--head] = height[i];
 77                     sum += lcp[head]-k+1;
 78                 }
 79                 if(sa[i] < len1) res += sum;
 80             }
 81         }
 82         for(int i = 1; i <= len; i++){
 83             if(height[i] < k){
 84                 sum = 0;
 85                 head = tail = maxn;
 86             }
 87             else{
 88                 for(int j = head; j < tail; j++){
 89                     if(lcp[j] > height[i]){
 90                         sum -= lcp[j]-height[i];
 91                         lcp[j] = height[i];
 92                     }
 93                     else break;
 94                 }
 95                 if(sa[i-1] < len1){
 96                     lcp[--head] = height[i];
 97                     sum += lcp[head]-k+1;
 98                 }
 99                 if(sa[i] > len1) res += sum;
100             }
101         }
102         printf("%I64d\n", res);
103     }
104 }

 

 

 

posted on 2013-11-17 08:40  pony1993  阅读(245)  评论(0编辑  收藏  举报

View My Stats