string string string
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1850 Accepted Submission(s): 546
Problem Description
Uncle Mao is a wonderful ACMER. One day he met an easy problem, but Uncle Mao was so lazy that he left the problem to you. I hope you can give him a solution.
Given a string s, we define a substring that happens exactly k times as an important string, and you need to find out how many substrings which are important strings.
Given a string s, we define a substring that happens exactly k times as an important string, and you need to find out how many substrings which are important strings.
Input
The first line contains an integer T (T≤100) implying the number of test cases.
For each test case, there are two lines:
the first line contains an integer k (k≥1) which is described above;
the second line contain a string s (length(s)≤105).
It's guaranteed that ∑length(s)≤2∗106.
For each test case, there are two lines:
the first line contains an integer k (k≥1) which is described above;
the second line contain a string s (length(s)≤105).
It's guaranteed that ∑length(s)≤2∗106.
Output
For each test case, print the number of the important substrings in a line.
Sample Input
2
2
abcabc
3
abcabcabcabc
Sample Output
6
9
Source
题意:
给一个字符串求其中恰好出现k次的子串的个数
代码:
//我们考虑每一个子串对结果的贡献,每个子串都是某个后缀的前缀,我们得到heigh数组之后可以维护一个长度是k的窗口,这个窗口中的后缀的 //lcp必然出现至少k次,然后再依次减去窗口左右端分别延长一位的lcp(即减去出现次数多于k次的lcp),这样他们中间的公共部分减了两次再加 //上就行了。注意临界端点的处理! #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int MAXN=100000; int sa[MAXN+9],ra[MAXN+9],he[MAXN+9],xx[MAXN+9],yy[MAXN+9],buc[MAXN+9]; char s[MAXN+9]; int len,m,f[MAXN+9][30]; 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; } } void rmq1() { for(int i=0;i<=len;i++) f[i][0]=he[i]; for(int j=1;(1<<j)<=len;j++){ for(int i=0;i+(1<<j)-1<=len;i++) f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]); } } int query(int l,int k) { if(l<0||l+k-1>=len) return 0; if(k==1) return len-sa[l]; int j=0,r=l+k-1;l++; while(1<<(j+1)<=r-l+1) j++; return min(f[l][j],f[r-(1<<j)+1][j]); } int main() { //freopen("in.txt","r",stdin); int t,k; scanf("%d",&t); while(t--){ scanf("%d",&k); scanf("%s",s); len=strlen(s); m=200; get_suf(); he[0]=he[len]=0; rmq1(); int ans=0; for(int i=0;i+k-1<len;i++) ans+=query(i,k)-query(i-1,k+1)-query(i,k+1)+query(i-1,k+2); printf("%d ",ans); } return 0; }