POJ 3415 Common Substrings (求长度大于K的公共子串个数,5级)
2013-09-10 18:48
429 查看
D - Common SubstringsCrawling in process...Crawling failedTime Limit:5000MSMemory Limit:65536KB 64bit IO Format:%I64d & %I64uSubmitStatusAppoint description:System Crawler (2013-08-31)DescriptionA 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 defineS, 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 andK.InputThe input file contains several blocks of data. For each block, the first line contains one integerK, followed by two lines containing strings A and B, respectively. The input file is ended byK=0.1 ≤ |A|, |B| ≤ 1051 ≤ K ≤ min{|A|, |B|}Characters of A and B are all Latin letters.OutputFor each case, output an integer |S|.Sample Input
2 aababaa abaabaa 1 xx xx 0Sample Output
22 5
思路:
#include<iostream>#include<cstring>#include<cstdio>#define FOR(i,a,b) for(int i=a;i<=b;++i)#define clr(f,z) memset(f,z,sizeof(f))using namespace std;const int msize=2e5+9;class SUFFIX_ARRAY{public:int sa[msize],h[msize],rank[msize],t1[msize],c[msize];bool cmp(int*r,int i,int k){return r[ sa[i] ]==r[ sa[i-1] ]&&r[ sa[i]+k ]==r[ sa[i-1]+k ];}void build_SA(int*s,int n,int m){ int*wx=t1,*wy=rank;FOR(i,0,m-1)c[i]=0;FOR(i,0,n-1)++c[ wx[i]=s[i] ];FOR(i,1,m-1)c[i]+=c[i-1];for(int i=n-1;i>=0;--i)sa[ --c[ wx[i] ] ]=i;for(int k=1;k<=n;k<<=1){int p=0;FOR(i,n-k,n-1)wy[p++]=i;FOR(i,0,n-1)if(sa[i]>=k)wy[p++]=sa[i]-k;FOR(i,0,m-1)c[i]=0;FOR(i,0,n-1)++c[ wx[ wy[i] ] ];FOR(i,1,m-1)c[i]+=c[i-1];for(int i=n-1;i>=0;--i)sa[ --c[ wx[ wy[i] ] ] ]=wy[i];swap(wx,wy);wx[ sa[0] ]=0;p=1;FOR(i,1,n-1)wx[ sa[i] ]=cmp(wy,i,k)?p-1:p++;if(p>=n)break;m=p;}}void get_H(int*s,int n){int k=0;FOR(i,0,n)rank[ sa[i] ]=i;FOR(i,0,n-1){if(k)--k;int j=sa[ rank[i]-1 ];while(s[i+k]==s[j+k])++k;h[ rank[i] ]=k;}}void debug(int n){printf("sa=");FOR(i,0,n)printf("%d ",sa[i]);puts("");printf("rank=");FOR(i,0,n)printf("%d ",rank[i]);puts("");printf("h=");FOR(i,0,n)printf("%d ",h[i]);puts("");}};SUFFIX_ARRAY ty;int len;int r[msize];char s1[msize],s2[msize];int sta[msize],stb[msize];int main(){while(scanf("%d",&len)&&len){scanf("%s%s",s1,s2);int len1=strlen(s1);int len2=strlen(s2);int len3=0;for(int i=0;s1[i];++i)r[i+len3]=s1[i];r[len3+len1]=128;len3+=len1+1;for(int i=0;s2[i];++i)r[ i+len3 ]=s2[i];r[ len3+len2 ]=129;len3+=len2+1;r[len3]=0;ty.build_SA(r,len3+1,300);ty.get_H(r,len3);// ty.debug(len3-1);long long ans=0;long long ss=0;int top=0;for(int i=2;i<=len3;i++){if(ty.h[i]<len){ss=0;top=0;continue;}int cnt=0;if(ty.sa[i-1]<len1){cnt++;ss+=ty.h[i]-len+1;}while(top>0 && ty.h[i]<=sta[top-1]){top--;ss-=stb[top]*(sta[top]-ty.h[i]);cnt+=stb[top];}sta[top]=ty.h[i];stb[top++]=cnt;if(ty.sa[i]>len1)ans+=ss;}ss=0;top=0;for(int i=2;i<=len3;i++){if(ty.h[i]<len){ss=0;top=0;continue;}int cnt=0;if(ty.sa[i-1]>len1){cnt++;ss+=ty.h[i]-len+1;}while(top>0 && ty.h[i]<=sta[top-1]){top--;ss-=stb[top]*(sta[top]-ty.h[i]);cnt+=stb[top];}sta[top]=ty.h[i];stb[top++]=cnt;if(ty.sa[i]<len1)ans+=ss;}printf("%I64d\n",ans);}}[/code]
相关文章推荐
- POJ 3415 Common Substrings (求长度大于K的公共子串个数,5级)
- POJ 题目3415 Common Substrings(后缀数组+栈,求可以匹配到的长度大于k的公共子串个数)
- POJ 3415 求两个字符串间长度不小于k的公共子串的个数
- 【后缀数组】 POJ 2774 Long Long Message 两个字符串的最长公共子串长度
- POJ 3415 Common Substrings(长度不小于k 的公共子串的个数--后缀数组+单调栈优化)
- poj 3415 后缀数组 两个字符串中长度不小于 k 的公共子串的个数
- poj 3415 Common Substrings(长度大于k的相同子串对数xian 后缀数组+单调桟统计)
- POJ - 3415 Common Substrings(后缀数组求长度不小于 k 的公共子串的个数+单调栈优化)
- POJ-Common Substrings(后缀数组-长度不小于 k 的公共子串的个数)
- 【POJ 3415】Common Substrings 长度不小于k的公共子串的个数
- POJ 3415 Common Substrings (后缀数组,长度不小于k的公共子串的个数)
- Poj 2774两个字符串的最长公共子串长度
- poj 3294 Life Forms(n个字符串中 求公共子串长度超过k得最大子串 后缀数组)
- poj 3415 :长度不小于 k 的公共子串的个数(后缀数组+单调栈)
- POJ - 3415 Common Substrings(后缀数组求长度不小于 k 的公共子串的个数+单调栈优化)
- POJ 2774-Long Long Message(后缀数组+高度数组-最大公共子串长度)
- POJ 题目2774 Long Long Message(后缀数组,求最长公共子串长度)
- POJ 2217-Secretary(后缀数组+高度数组-最大公共子串长度)
- (Relax 后缀数组1.3)POJ 3415 Common Substrings(求串A和串B中长度不小于k的公共子串数)
- POJ - 3415 Common Substrings 求2个串大于K的公共子串个数