HUST 1352 Repetitions of Substrings(字符串)

Repetitions of Substrings

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

先记录一下,完全不知道怎么回事。

#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;  
}  
View Code

 

posted @ 2016-02-18 13:28  ACMSaga  阅读(300)  评论(0编辑  收藏  举报