Common Substrings
Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 7605 | Accepted: 2524 |
Description
A substring of a string T is defined as:
T(i, k)=TiTi+1...Ti+k-1, 1≤i≤i+k-1≤|T|.
Given two strings A, B and one integer K, we define S, a set of triples (i, j, k):
S = {(i, j, k) | k≥K, A(i, k)=B(j, k)}.
You are to give the value of |S| for specific A, B and K.
Input
The input file contains several blocks of data. For each block, the first line contains one integer K, followed by two lines containing strings A and B, respectively. The input file is ended by K=0.
1 ≤ |A|, |B| ≤ 105
1 ≤ K ≤ min{|A|, |B|}
Characters of A and B are all Latin letters.
Output
For each case, output an integer |S|.
Sample Input
2 aababaa abaabaa 1 xx xx 0
Sample Output
22 5
题意:
给出两个串,问这两个串的所有的子串中(重复出现的,只要是位置不同就算两个子串),长度大于等于k的公共子串有多少个。
思路:
这个也是后缀自动机的比较好的题目.....
用一个串构建好后缀自动机,然后我们在这个串上面跑另外一个串,我们在这里应用上之前的spoj1811的匹配个数....
那么这样的串出现了多少次呢?....
就是spoj8222中的那个迭代更新的字串表示这个长度的子串出现了多少次的Right数组.....
我们这个东西就出现了 cnt * Right 次...真是太神奇了.....
1 #include<cstdlib> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #ifdef WIN32 6 #define fmt64 "%I64d" 7 #else 8 #define fmt64 "%lld" 9 #endif 10 using namespace std; 11 const int maxn = (int)2.5e5,sigma = 26; 12 char str[maxn]; 13 int k; 14 int cmp(int, int); 15 struct Sam{ 16 int ch[maxn][sigma << 1],par[maxn],stp[maxn],right[maxn],times[maxn],id[maxn]; 17 int sz,last; 18 int idx(char x){ 19 if(‘a‘ <= x && x <= ‘z‘) return x - ‘a‘; 20 else return x - ‘A‘ + 26; 21 } 22 void init(){ 23 for(int i = 1; i <= sz; ++i){ 24 memset(ch[i],0,sizeof(ch[i])); 25 right[i] = times[i] = par[i] = stp[i] = 0; 26 } 27 sz = last = 1; 28 } 29 void add(int c){ 30 stp[++sz] = stp[last] + 1; 31 int p = last, np = sz; 32 for(; !ch[p][c]; p = par[p]) ch[p][c] = np; 33 if(!p) par[np] = 1; 34 else{ 35 int q = ch[p][c]; 36 if(stp[q] != stp[p] + 1){ 37 stp[++sz] = stp[p] + 1; 38 int nq = sz; 39 memcpy(ch[nq],ch[q],sizeof(ch[q])); 40 par[nq] = par[q]; 41 par[q] = par[np] = nq; 42 for(; ch[p][c] == q; p = par[p]) ch[p][c] = nq; 43 } 44 else par[np] = q; 45 } 46 last = np; 47 } 48 void ins(char *pt){ 49 int i; 50 init(); 51 for(i = 0; pt[i]; ++i) add(idx(pt[i])); 52 } 53 void prep(char *pt){ 54 int i,x = 1; 55 for(i = 1; i <= sz; ++i) id[i] = i; 56 sort(id + 1, id + sz + 1, cmp); 57 for(i = 0; pt[i]; ++i){ 58 x = ch[x][idx(pt[i])]; 59 ++right[x]; 60 } 61 for(i = 1; i <= sz; ++i) 62 if(par[id[i]]) right[par[id[i]]] += right[id[i]]; 63 } 64 void comp(char *pt){ 65 int i,x = 1,match = 0; 66 long long ans = 0; 67 for(i = 0; pt[i]; ++i){ 68 if(ch[x][idx(pt[i])]){ 69 x = ch[x][idx(pt[i])]; 70 match++; 71 } 72 else{ 73 while(x && !ch[x][idx(pt[i])]) x = par[x]; 74 if(!x) x = 1, match = 0; 75 else match = stp[x] + 1, x = ch[x][idx(pt[i])]; 76 } 77 if(match >= k){ 78 ans += (long long)(match - max(k, stp[par[x]] + 1) + 1) * right[x]; 79 if(par[x] && k <= stp[par[x]]) times[par[x]]++; 80 } 81 } 82 for(i = 1; i <= sz; ++i){ 83 int t = id[i]; 84 ans += (long long)times[t] * right[t] * (stp[t] - max(k, stp[par[t]] + 1) + 1); 85 if(par[t] && k <= stp[par[t]]) times[par[t]] += times[t]; 86 } 87 printf(fmt64"\n",ans); 88 } 89 }sam; 90 int cmp(int x,int y){ 91 return sam.stp[x] > sam.stp[y]; 92 } 93 int main() 94 { 95 freopen("csb.in","r",stdin); 96 freopen("csb.out","w",stdout); 97 while(scanf("%d\n",&k) != EOF,k){ 98 scanf("%s\n",str); 99 sam.ins(str); 100 sam.prep(str); 101 scanf("%s\n",str); 102 sam.comp(str); 103 } 104 return 0; 105 }