Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 11469 | Accepted: 3796 |
Descriptionios
A substring of a string T is defined as:數組
Given two strings A, B and one integer K, we define S, a set of triples (i, j, k):spa
You are to give the value of |S| for specific A, B and K.code
Inputblog
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.ip
1 ≤ |A|, |B| ≤ 105
1 ≤ K ≤ min{|A|, |B|}
Characters of A and B are all Latin letters.ci
Output字符串
For each case, output an integer |S|.get
Sample Inputinput
2 aababaa abaabaa 1 xx xx 0
Sample Output
22 5
Source
//論文題,按照規矩先把兩個串連起來求出heigh數組,heigh數組分組(大於等於k的一組),而後每遇到一個B串就讓他和前面的A串求 //lcp,貢獻就是lcp-k+1,而後反過來再求一次每一個A和前面的B的,但這是n^2的。咱們考慮求某個B與前面的A的lcp時是求這一段中的最小 //的heigh值,這樣咱們能夠用一個遞增的棧來存儲heigh數組把貢獻疊加起來,要入棧的元素小於棧頂時對後面的B的貢獻值會減少,而且 //還要保存由於他的入棧而出棧了多少大於等於他的元素以備後面的操做(減少貢獻值),每遇到B就更新答案。 //這題仍是很難的 #include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; const int MAXN=300000; int sa[MAXN+9],he[MAXN+9],ra[MAXN+9],xx[MAXN+9],yy[MAXN+9],buc[MAXN+9],q[MAXN+9][2]; char s[MAXN+9]; int len,m; void get_suf() { int *x=xx,*y=yy; for(int i=0;i<m;i++) buc[i]=0; for(int i=0;i<len;i++) buc[x[i]=s[i]]++; for(int i=1;i<m;i++) buc[i]+=buc[i-1]; for(int i=len-1;i>=0;i--) sa[--buc[x[i]]]=i; for(int k=1;k<=len;k<<=1){ int p=0; for(int i=len-1;i>=len-k;i--) y[p++]=i; for(int i=0;i<len;i++) if(sa[i]>=k) y[p++]=sa[i]-k; for(int i=0;i<m;i++) buc[i]=0; for(int i=0;i<len;i++) buc[x[y[i]]]++; for(int i=1;i<m;i++) buc[i]+=buc[i-1]; for(int i=len-1;i>=0;i--) sa[--buc[x[y[i]]]]=y[i]; swap(x,y); p=1;x[sa[0]]=0; for(int i=1;i<len;i++){ if(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]) x[sa[i]]=p-1; else x[sa[i]]=p++; } if(p>=len) break; m=p; } for(int i=0;i<len;i++) ra[sa[i]]=i; int k=0; for(int i=0;i<len;i++){ if(ra[i]==0) { he[0]=0; continue; } if(k) k--; int j=sa[ra[i]-1]; while(s[i+k]==s[j+k]&&i+k<len&&j+k<len) k++; he[ra[i]]=k; } } ll solve(int len1,int k) { ll ans=0,cnt=0,sum=0,top=0; for(int i=1;i<len;i++){ if(he[i]<k) { top=sum=0;continue; } cnt=0; if(sa[i-1]<len1) { cnt++;sum+=he[i]-k+1; } while(top&&he[i]<=q[top][1]){ sum-=q[top][0]*(q[top][1]-he[i]); cnt+=q[top--][0]; } q[++top][0]=cnt; q[top][1]=he[i]; if(sa[i]>len1) ans+=sum; } sum=0;top=0; for(int i=1;i<len;i++){ if(he[i]<k) { top=sum=0;continue; } cnt=0; if(sa[i-1]>len1) { cnt++;sum+=he[i]-k+1; } while(top&&he[i]<=q[top][1]){ sum-=q[top][0]*(q[top][1]-he[i]); cnt+=q[top--][0]; } q[++top][0]=cnt; q[top][1]=he[i]; if(sa[i]<len1) ans+=sum; } return ans; } int main() { int k; while(scanf("%d",&k)&&k){ scanf("%s",s); int len1=strlen(s); s[len1]='#'; scanf("%s",s+len1+1); len=strlen(s); m=200; get_suf(); printf("%lld\n",solve(len1,k)); } return 0; }