Description
The “repetitions” of a string S(whose length is n) is a maximum number “k” such that:
1) k is a factor of n
2) S[0..n/k-1] = S[p*(n/k)..(p+1)*(n/k)-1] for all that (1 <= p < n/k)
for example:
the repetitions of “aaaaaa”is 6.
the repetitions of “abababab”is 4.
the repetitions of “abcdef”is 1.
Now, given a string S and a number K, please tell me how many substrings of S have repetitions NOT less than K.
Input
The input consists of several instances, each one for a single line.
S K
S is a string, K is a number. Check the Description for their meanings.
S contains lowercase letters(ie ‘a‘..‘z‘) only.
1 <= length of S <= 100000.
1 <= K <= length of S.
Output
For each instance, output the number of substring whose repetitions is NOT less than K.
Sample Input
abcabc 2 acmac 3
Sample Output
1 0
题意:输入字符串,k,求重复次数不小于k的子串的个数。
解题思路:枚举字串长度,遍历所有的串,根据lcp向前扩展,更新答案。
代码:
/* *********************************************** Author :xianxingwuguan Created Time :2014-1-29 20:43:51 File Name :4.cpp ************************************************ */ #pragma comment(linker, "/STACK:102400000,102400000") #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <math.h> #include <stdlib.h> #include <time.h> using namespace std; const int maxn=300300; int height[maxn],sa[maxn],rank[maxn],c[maxn],t1[maxn],t2[maxn]; void da(int *str,int n,int m) { int i,j,k,p,*x=t1,*y=t2; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[i]=str[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(k=1;k<=n;k<<=1) { p=0; for(i=n-k;i<n;i++)y[p++]=i; for(i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k; 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]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++; if(p>=n)break; m=p; } } void calheight(int *str,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(str[i+k]==str[j+k])k++; height[rank[i]]=k; } // printf("sa:");for(i=0;i<=n;i++)printf("%d ",sa[i]);puts(""); // printf("rank:");for(i=0;i<=n;i++)printf("%d ",rank[i]);puts(""); // printf("height:");for(i=0;i<=n;i++)printf("%d ",height[i]);puts(""); } int str[maxn]; char ss[maxn]; int Log[maxn]; int best[23][maxn]; void init(int n) { int i,j; Log[0]=-1; for(i=1;i<=n;i++) Log[i]=(i&(i-1))?Log[i-1]:Log[i-1]+1; for(i=1;i<=n;i++)best[0][i]=height[i]; for(i=1;i<=Log[n];i++) for(j=1;j<=n;j++) best[i][j]=min(best[i-1][j],best[i-1][j+(1<<(i-1))]); } int lcp(int a,int b) { a=rank[a]; b=rank[b]; if(a>b)swap(a,b); a++; int t=Log[b-a+1]; return min(best[t][a],best[t][b-(1<<t)+1]); } int rep[maxn]; int main() { //freopen("data.in","r",stdin); //freopen("data.out","w",stdout); int i,j,k,m,n,p; while(~scanf("%s%d",&ss,&k)) { n=strlen(ss); if(k==1) { printf("%lld\n",(long long)n*(n+1)/2); continue; } for(i=0;i<n;i++)str[i]=ss[i]; str[n]=0; da(str,n+1,300); calheight(str,n); init(n); for(i=0;i<=n;i++)rep[i]=1; for(int L=1;L*k<=n;L++) { for(i=0;i<n;i+=L) { int t=lcp(i,i+L); if(!t)continue; j=0; while(j<=i&&j<L&&str[i-j]==str[i-j+L]) { if(t>=L&&lcp(i-j,i-j+L)>=(k-1)*L) rep[i-j]=max(rep[i-j],t/L+1); j++;t++; } } } int ans=0; for(i=0;i<=n;i++)if(rep[i]>=k)ans+=rep[i]-k+1; printf("%d\n",ans); } return 0; }