POJ 3415 Common Substrings (求长度不小于k的公共子串的个数)
2016-08-18 22:10
501 查看
[b]Common Substrings[/b]
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
Sample Output
Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 10002 | Accepted: 3302 |
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
/* * POJ 3415 Common Substrings * 给出两个字符串A,B,求长度不小于k的公共子串的个数 * * 将B接到A的后面,中间用一个没出现的字符隔开,然后求sa和height数组 * 然后按height分组,我们只考虑height[i]>=k的后缀,因为小于不符合题意,然后对于每个分组,统计答案 * 很容易想到算法就是对于同一组里面的B后缀,我和前面的所有A的后缀比较,累加答案,再反过来对A做一遍即可 * 这样的时间复杂度是O(n*n)的,会TLE * 考虑这样的一个性质,后缀i和j的lcp是height[rank[i+1]]...height[rank[j]]的最小值,那么对于 * height[i]==s&&sa[i]是B的后缀,它和前面A的答案肯定是最小的height的累加,于是这样我们可以用一个 * 单调栈来维护,每当新加入的height小于栈顶的元素,我们就把栈顶元素弹出来,把新的值压入栈中 * 怎么统计答案呢?可以先加后减,当计算B的个数时,遇到A的后缀我们就直接累加到答案中,如果和栈顶元素冲突了 * 说明多加了一部分,在弹出元素时减去即可,这样多维护一个个数就行了。 */ #include <stdio.h> #include <string.h> #include <iostream> using namespace std; const int MAXN = 200000+100; int sa[MAXN]; int t1[MAXN],t2[MAXN],c[MAXN]; int Rank[MAXN],height[MAXN]; void build_sa(int s[],int n,int m) { int i,j,p,*x=t1,*y=t2; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[i]=s[i]]++; for(i=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i; for(j=1;j<=n;j<<=1) { p=0; for(i=n-j;i<n;i++)y[p++]=i; for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[y[i]]]++; for(i=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1;x[sa[0]]=0; for(i=1;i<n;i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++; if(p>=n)break; m=p; } } void getHeight(int s[],int n) { int i,j,k=0; for(i=0;i<=n;i++) Rank[sa[i]]=i; for(i=0;i<n;i++) { if(k)k--; j=sa[Rank[i]-1]; while(s[i+k]==s[j+k])k++; height[Rank[i]]=k; } } char str1[MAXN],str2[MAXN]; int ss[MAXN]; int sta[MAXN],stb[MAXN]; int main() { int k; while(scanf("%d",&k)==1&&k) { scanf("%s",str1); scanf("%s",str2); int len1=strlen(str1); int len2=strlen(str2); int n=len1+len2+1; for(int i=0;i<len1;i++) ss[i]=str1[i]; ss[len1]=1; for(int i=0;i<len2;i++) ss[len1+i+1]=str2[i]; ss =0; build_sa(ss,n+1,128); getHeight(ss,n); long long ans=0; long long res=0; int top=0; for(int i=2;i<=n;i++) { if(height[i]<k) { res=0; top=0; continue; } int cnt=0; if(sa[i-1]<len1) { cnt++; res+=height[i]-k+1; } while(top>0&&height[i]<=sta[top-1]) { top--; res-=stb[top]*(sta[top]-height[i]); cnt+=stb[top]; } sta[top]=height[i],stb[top++]=cnt; if(sa[i]>len1) ans+=res; } res=0,top=0; for(int i=2;i<=n;i++) { if(height[i]<k) { res=0; top=0; continue; } int cnt=0; if(sa[i-1]>len1) { cnt++; res+=height[i]-k+1; } while(top>0&&height[i]<=sta[top-1]) { top--; res-=stb[top]*(sta[top]-height[i]); cnt+=stb[top]; } sta[top]=height[i],stb[top++]=cnt; if(sa[i]<len1) ans+=res; } printf("%lld\n",ans); } return 0; }
相关文章推荐
- POJ - 3415 Common Substrings(后缀数组求长度不小于 k 的公共子串的个数+单调栈优化)
- POJ 3415 求两个字符串间长度不小于k的公共子串的个数
- POJ - 3415 Common Substrings(后缀数组求长度不小于 k 的公共子串的个数+单调栈优化)
- poj 3415 后缀数组 两个字符串中长度不小于 k 的公共子串的个数
- POJ 3415 Common Substrings(长度不小于K的公共子串的个数+后缀数组+height数组分组思想+单调栈)
- (Relax 后缀数组1.3)POJ 3415 Common Substrings(求串A和串B中长度不小于k的公共子串数)
- poj 3415 :长度不小于 k 的公共子串的个数(后缀数组+单调栈)
- POJ 3415 Common Substrings(长度不小于k 的公共子串的个数--后缀数组+单调栈优化)
- 【POJ 3415】Common Substrings 长度不小于k的公共子串的个数
- POJ 3415 Common Substrings (后缀数组,长度不小于k的公共子串的个数)
- poj 3415 长度超过K的公共子串个数
- POJ 3415-Common Substrings(后缀数组+单调栈-公共子串的长度)
- hdu 3415 后缀数组 长度不小于 k 的公共子串的个数
- POJ 3415 不小于k的公共子串的个数
- POJ 3415 不小于k的公共子串的个数
- POJ 题目3415 Common Substrings(后缀数组+栈,求可以匹配到的长度大于k的公共子串个数)
- POJ-Common Substrings(后缀数组-长度不小于 k 的公共子串的个数)
- 【后缀数组】 POJ 2774 Long Long Message 两个字符串的最长公共子串长度
- 【poj3415-长度不小于k的公共子串个数】后缀数组+单调栈
- 后缀数组(长度不小于k的公共子串的个数)