POJ3415 Common Substrings

后缀数组 求长度不小于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 }

 

 

 

你可能感兴趣的:(substring)