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