[HDU]3518——Boring counting
Posted QYP_2002
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HDU]3518——Boring counting相关的知识,希望对你有一定的参考价值。
zhan.jiang.ou now faced a tough problem,his english teacher quan.hong.chun 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”).
题目大意:求一个字符串的不重叠子串的个数。
思路:我真是太辣鸡了,其实这个题就是后缀数组性质②的应用,只不过是求出每个长度的答案(性质详见我的后缀数组的基本使用技巧)!
总结:后缀数组英语应用太灵活,多回顾反思!
1 #include<map> 2 #include<set> 3 #include<list> 4 #include<deque> 5 #include<cmath> 6 #include<queue> 7 #include<stack> 8 #include<vector> 9 #include<cstdio> 10 #include<complex> 11 #include<cstring> 12 #include<cstdlib> 13 #include<iostream> 14 #include<algorithm> 15 #define LL long long 16 #define db double 17 #define RG register 18 #define maxx 1001 19 #define Inf 666666 20 using namespace std;int tong[maxx]; 21 int sa[maxx],X[maxx],Y[maxx],rnk[maxx],height[maxx],num[maxx];char s[maxx]; 22 bool comp(int *r,int a,int b,int len){ 23 return r[a]==r[b]&&r[a+len]==r[b+len]; 24 } 25 void build_sa(int len){ 26 int *x=X,*y=Y,*t,Max=maxx/2; 27 memset(tong,0,sizeof(tong)); 28 for(int i=0;i<len;++i) 29 tong[x[i]=num[i]]++; 30 for(int i=1;i<=Max;++i) 31 tong[i]+=tong[i-1]; 32 for(int i=len-1;i!=-1;i--) 33 sa[--tong[x[i]]]=i; 34 for(int j=1,p=1,i;p<len;j<<=1,Max=p){ 35 for(i=len-1,p=0;i>=len-j;--i)y[p++]=i; 36 for(i=0;i<len;++i) 37 if(sa[i]>=j)y[p++]=sa[i]-j; 38 for(i=0;i<=Max;++i) 39 tong[i]=0; 40 for(i=0;i<len;++i) 41 tong[x[y[i]]]++; 42 for(i=1;i<Max;++i) 43 tong[i]+=tong[i-1]; 44 for(i=len-1;i!=-1;i--) 45 sa[--tong[x[y[i]]]]=y[i]; 46 for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<len;++i) 47 x[sa[i]]=comp(y,sa[i],sa[i-1],j)?p-1:p++; 48 } 49 }int n; 50 void geth(){ 51 int j,k=0; 52 for(int i=1;i<=n;++i) 53 rnk[sa[i]]=i; 54 for(int i=0;i<n;height[rnk[i++]]=k) 55 for(k?k--:0,j=sa[rnk[i]-1];num[i+k]==num[j+k];k++); 56 } 57 void ans(){LL ans=0; 58 for(RG int len=1;len<=(n/2);++len){ 59 int Max=-Inf,Min=Inf; 60 for(RG int i=1;i<=n;++i){ 61 if(height[i]<len){ 62 if(Max-Min>=len)ans++; 63 Max=-Inf,Min=Inf; 64 } 65 Max=max(Max,sa[i]); 66 Min=min(Min,sa[i]); 67 if(i==n&&Max-Min>=len)ans++; 68 } 69 } 70 printf("%lld\\n",ans); 71 } 72 int main(){ 73 while(scanf("%s",s)){ 74 n=strlen(s); 75 if(n==1&&s[0]==\'#\')break; 76 memset(rnk,0,sizeof(rnk)); 77 memset(height,0,sizeof(height)); 78 memset(sa,0,sizeof(sa)); 79 memset(X,0,sizeof(X)); 80 memset(Y,0,sizeof(Y)); 81 for(int i=0;i<n;++i) 82 num[i]=s[i]-55; 83 num[n]=0; 84 build_sa(n+1); 85 geth(); 86 ans(); 87 } 88 return 0; 89 }
以上是关于[HDU]3518——Boring counting的主要内容,如果未能解决你的问题,请参考以下文章
Boring counting HDU - 3518 (后缀数组)