Boring counting
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 1359 Accepted Submission(s): 546
Problem Description
035 now faced a tough problem,his english teacher gives him a string,which consists with n lower case letter,he must figure out how many substrings appear at least twice,moreover,such apearances can not overlap each other.
Take aaaa as an example.”a” apears four times,”aa” apears two times without overlaping.however,aaa can’t apear more than one time without overlaping.since we can get “aaa” from [0-2](The position of string begins with 0) and [1-3]. But the interval [0-2] and [1-3] overlaps each other.So “aaa” can not take into account.Therefore,the answer is 2(“a”,and “aa”).
Take aaaa as an example.”a” apears four times,”aa” apears two times without overlaping.however,aaa can’t apear more than one time without overlaping.since we can get “aaa” from [0-2](The position of string begins with 0) and [1-3]. But the interval [0-2] and [1-3] overlaps each other.So “aaa” can not take into account.Therefore,the answer is 2(“a”,and “aa”).
Input
The input data consist with several test cases.The input ends with a line “#”.each test case contain a string consists with lower letter,the length n won’t exceed 1000(n <= 1000).
Output
For each test case output an integer ans,which represent the answer for the test case.you’d better use int64 to avoid unnecessary trouble.
Sample Input
aaaa ababcabb aaaaaa #
Sample Output
2 3 3 给定一个字符串,求有多少子串至少重复两次。 解题思路:首先根据后缀数组倍增法预处理出sa,height值,然后枚举长度,根据height值分组统计。 代码:/* *********************************************** Author :xianxingwuguan Created Time :2014/1/19 11:14:49 File Name :3.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=100010; char str[maxn]; int sa[maxn],height[maxn],t[maxn],t2[maxn],c[maxn],rank[maxn]; void da(char *str,int n,int m) { int i,j,k,p,*x=t,*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-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; if(p>=n)break; m=p; } } void calheight(char *s,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(s[i+k]==s[j+k])k++; height[rank[i]]=k; } // cout<<"sa:";for(i=0;i<=n;i++)cout<<sa[i]<<" ";cout<<endl; // cout<<"rank:";for(i=0;i<=n;i++)cout<<rank[i]<<" ";cout<<endl; // cout<<"height:";for(i=0;i<=n;i++)cout<<height[i]<<" ";cout<<endl; } int main() { //freopen("data.in","r",stdin); //freopen("data.out","w",stdout); int i,j,k,m,n; while(~scanf("%s",str)&&str[0]!='#') { n=strlen(str); da(str,n+1,300); calheight(str,n); int ans=0; for(i=1;2*i<=n;i++) { int l=n+1,r=-1; for(j=2;j<=n;j++) { if(height[j]<i) { if(r-l>=i)ans++; l=n+1; r=-1; } else { l=min(l,sa[j]); l=min(l,sa[j-1]); r=max(r,sa[j]); r=max(r,sa[j-1]); } } if(r-l>=i)ans++; } cout<<ans<<endl; } return 0; }