HUST 1352 求重复次数不小于k的子串的个数。

来源:互联网 发布:java c 编辑:程序博客网 时间:2024/05/17 04:01
M - M
Time Limit:20000MS    Memory Limit:131072KB    64bit IO Format:%lld & %llu
SubmitStatus
Appoint description:

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 2acmac 3

Sample Output

10


题意:输入字符串,k,求重复次数不小于k的子串的个数。

解题思路:枚举字串长度,遍历所有的串,根据lcp向前扩展,更新答案。

代码:

/* ***********************************************Author :xianxingwuguanCreated Time :2014-1-29 20:43:51File 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;}


2 0
原创粉丝点击