POJ3415 Common Substrings

时间:2023-03-09 07:46:02
POJ3415 Common Substrings

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

代码:

 #include <stdio.h>
#include <string.h> const int maxn = ;
int len, len1;
int wa[maxn], wb[maxn], wv[maxn], wd[maxn], sa[maxn];
int lcp[maxn], r[maxn], rank[maxn], height[maxn]; int cmp(int *r, int a, int b, int l){
return r[a] == r[b] && r[a+l] == r[b+l];
} void da(int *r, int n, int m){
int i, j, p, *x=wa, *y=wb, *t;
for(i = ; i < m; i++) wd[i] = ;
for(i = ; i < n; i++) wd[x[i] = r[i]]++;
for(i = ; i < m; i++) wd[i] += wd[i-];
for(i = n-; i >= ; i--) sa[--wd[x[i]]] = i;
for(j = , p = ; p < n; j *= , m = p){
for(p = , i = n-j; i < n; i++) y[p++] = i;
for(i = ; i < n; i++) if(sa[i] >= j) y[p++] = sa[i]-j;
for(i = ; i < n; i++) wv[i] = x[y[i]];
for(i = ; i < m; i++) wd[i] = ;
for(i = ; i < n; i++) wd[wv[i]]++;
for(i = ; i < m; i++) wd[i] += wd[i-];
for(i = n-; i >= ; i --) sa[--wd[wv[i]]] = y[i];
for(t = x, x = y, y = t, p = , x[sa[]] = , i = ; i < n; i++){
x[sa[i]] = cmp(y, sa[i-], sa[i], j) ? p-: p++;
}
}
} void calHeight(int *r, int n){
int i, j, k = ;
for(i = ; i <= n; i++) rank[sa[i]] = i;
for(i = ; i < n; height[rank[i++]] = k){
for(k ? k-- : , j = sa[rank[i]-]; r[i+k] == r[j+k]; k++);
}
} int main(){
int k;
char str1[maxn], str2[maxn];
while(~scanf("%d", &k)){
if(k==) break;
scanf("%s%s",str1, str2);
len1 = strlen(str1);
len = strlen(str2);
for(int i = ; i < len1; i++){
r[i] = str1[i];
}
r[len1] = '$';
for(int i = ; i < len; i++){
r[i+len1+] = str2[i];
}
len += len1+;
r[len] = ;
da(r, len+, );
calHeight(r, len);
long long res = , sum;
int head, tail;
for(int i = ; i <= len; i++){
if(height[i] < k){
sum = ;
head = tail = maxn;
}
else{
for(int j = head; j < tail; j++){
if(lcp[j] > height[i]){
sum -= lcp[j]-height[i];
lcp[j] = height[i];
}
else break;
}
if(sa[i-] > len1){
lcp[--head] = height[i];
sum += lcp[head]-k+;
}
if(sa[i] < len1) res += sum;
}
}
for(int i = ; i <= len; i++){
if(height[i] < k){
sum = ;
head = tail = maxn;
}
else{
for(int j = head; j < tail; j++){
if(lcp[j] > height[i]){
sum -= lcp[j]-height[i];
lcp[j] = height[i];
}
else break;
}
if(sa[i-] < len1){
lcp[--head] = height[i];
sum += lcp[head]-k+;
}
if(sa[i] > len1) res += sum;
}
}
printf("%I64d\n", res);
}
}