HDU 3518 Boring counting(后缀数组,字符处理)
2014-08-20 11:12
363 查看
题目
参考自:http://blog.sina.com.cn/s/blog_64675f540100k9el.html
题目描述:
找出一个字符串中至少重复出现两次的字串的个数(重复出现时不能重叠)。
解题报告:
后缀数组即可解之。
枚举字串长度h
对于每一次的h,利用height数组,找出连续的height大于等于h的里面最左端和最右端得为之l和r。
如果l + h - 1 < r的话,说明没有重叠,答案加1.
O(n^2)复杂度。
View Code
参考自:http://blog.sina.com.cn/s/blog_64675f540100k9el.html
题目描述:
找出一个字符串中至少重复出现两次的字串的个数(重复出现时不能重叠)。
解题报告:
后缀数组即可解之。
枚举字串长度h
对于每一次的h,利用height数组,找出连续的height大于等于h的里面最左端和最右端得为之l和r。
如果l + h - 1 < r的话,说明没有重叠,答案加1.
O(n^2)复杂度。
#include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> using namespace std; #define maxn 1010 int wa[maxn],wb[maxn],wv[maxn],ws[maxn]; int cmp(int *r,int a,int b,int l) {return r[a]==r[b]&&r[a+l]==r[b+l];} void da(int *r,int *sa,int n,int m) { int i,j,p,*x=wa,*y=wb,*t; for(i=0;i<m;i++)ws[i]=0; for(i=0;i<n;i++)ws[x[i]=r[i]]++; for(i=1;i<m;i++)ws[i]+=ws[i-1]; for(i=n-1;i>=0;i--)sa[--ws[x[i]]]=i; for(j=1,p=1;p<n;j*=2,m=p) { for(p=0,i=n-j;i<n;i++)y[p++]=i; for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(i=0;i<n;i++)wv[i]=x[y[i]]; for(i=0;i<m;i++)ws[i]=0; for(i=0;i<n;i++)ws[wv[i]]++; for(i=1;i<m;i++)ws[i]+=ws[i-1]; for(i=n-1;i>=0;i--)sa[--ws[wv[i]]]=y[i]; for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; } } int rankk[maxn],height[maxn]; void calheight(int *r,int *sa,int n) { int i,j,k=0; for(i=1;i<=n;i++)rankk[sa[i]]=i; for(i=0;i<n;height[rankk[i++]]=k) for(k?k--:0,j=sa[rankk[i]-1];r[i+k]==r[j+k];k++); } int main() { char s[1010]; while(scanf("%s",s)!=EOF) { if(strcmp(s,"#")==0)break; int len=strlen(s); int r[1010],sa[1010]; //又忘记初始化排名了 for(int i=0;i<len;i++)r[i]=s[i]; r[len]=0;//zui hou yi ge zui xiao ,ji shu pai xu de xu yao da(r,sa,len+1,130); calheight(r,sa,len); //mei ju chang du int nn=len/2; int ans=0,minn,maxx; for(int i=1;i<=nn;i++) { minn=1010,maxx=-1; for(int j=2;j<=len;j++) { ////有字串会被重复计算,所以不能这么写 //if(height[j]>=i) //{ // minn=min(sa[j],sa[j-1]); // maxx=max(sa[j],sa[j-1]); // if(minn+i<=maxx)ans++; //} //好好观察height数组的特性,可以这么写来避免重复计算 if(height[j]>=i) { minn=min(minn,min(sa[j],sa[j-1])); maxx=max(maxx,max(sa[j],sa[j-1])); } else { if(minn+i<=maxx)ans++; minn=1010,maxx=-1; } } if(minn+i<=maxx)ans++; } printf("%d\n",ans); } return 0; }
View Code
相关文章推荐
- 后缀数组 --- HDU 3518 Boring counting
- hdu 3518 Boring counting 后缀数组基础题
- HDU 3518 Boring counting[后缀数组]
- HDU 3518 Boring counting(后缀数组 所有不重叠字串出现两次以上的次数)
- HDU 3518 Boring counting(后缀数组入门题)
- Hdu 3518 Boring counting 后缀数组
- HDU 3518 Boring counting 后缀自动机
- HDU 3518 Boring Counting 后缀数组/后缀自动机
- HDU 3518 后缀数组
- hdu 3158 Boring counting 后缀数组
- HDOJ 题目3518 Boring counting(后缀数组,求不重叠反复次数最少为2的子串种类数)
- hdu 3518 后缀数组
- HDOJ 题目3518 Boring counting(后缀数组,求不重叠重复次数最少为2的子串种类数)
- 【后缀数组】 HDOJ 3518 Boring counting
- hdoj 3518 Boring counting 【后缀数组】
- 杭电hdu 3518 boring counting 后缀数组学习
- 后缀数组--处理字符串的利器
- HDU 3518 Boring counting(后缀数组)
- 后缀数组——处理字符串的有力工具
- 字符串相关处理kmp,前缀数,后缀树,后缀数组,最长回文串,最长重复字串,最长非重复字串