hdu3518 Boring counting(后缀数组)
2015-09-04 13:43
363 查看
题目链接:这里写链接内容
题目描述:给一个字符串,统计该字符串中所有重复出现超过两次的子串的数量
1、重复出现的两个子串之间不能重叠
2、相同的子串只能算一次
解题思路:后缀数组da
1、枚举子串可能的长度,对于长度i我们遍历height数组,如果height[j]>=i说明sa[j-1]与sa[j]的最长公共前缀长度大于i,更新minx(保存长度大于i的最长公共前缀中下标最小的位置),maax同理,此时不能ans++;我们要继续观察如果height[j+1]>=i,则说明sa[j-1],sa[j],sa[j+1]的最长公共前缀大于等于i,为满足条件2我们只能计算一次,所以直到height[j]
题目描述:给一个字符串,统计该字符串中所有重复出现超过两次的子串的数量
1、重复出现的两个子串之间不能重叠
2、相同的子串只能算一次
解题思路:后缀数组da
1、枚举子串可能的长度,对于长度i我们遍历height数组,如果height[j]>=i说明sa[j-1]与sa[j]的最长公共前缀长度大于i,更新minx(保存长度大于i的最长公共前缀中下标最小的位置),maax同理,此时不能ans++;我们要继续观察如果height[j+1]>=i,则说明sa[j-1],sa[j],sa[j+1]的最长公共前缀大于等于i,为满足条件2我们只能计算一次,所以直到height[j]
#include <cstdio> #include <cstring> #include <iostream> #define maxn 1010 typedef unsigned long long ll; using namespace std; int wa[maxn],wb[maxn],wv[maxn],ww[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++) ww[i]=0; for(i=0;i<n;i++) ww[x[i]=r[i]]++; for(i=1;i<m;i++) ww[i]+=ww[i-1]; for(i=n-1;i>=0;i--) sa[--ww[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++) ww[i]=0; for(i=0;i<n;i++) ww[wv[i]]++; for(i=1;i<m;i++) ww[i]+=ww[i-1]; for(i=n-1;i>=0;i--) sa[--ww[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++; } return; } int ranks[maxn],height[maxn]; void calheight(int *r,int *sa,int n) { int i,j,k=0; for(i=1;i<=n;i++) ranks[sa[i]]=i; for(i=0;i<n;height[ranks[i++]]=k) for(k?k--:0,j=sa[ranks[i]-1];r[i+k]==r[j+k];k++); return; } int RMQ[maxn]; int mm[maxn]; int best[20][maxn]; void initRMQ(int n) { int i,j,a,b; for(mm[0]=-1,i=1;i<=n;i++) mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1]; for(i=1;i<=n;i++) best[0][i]=i; for(i=1;i<=mm ;i++) for(j=1;j<=n+1-(1<<i);j++) { a=best[i-1][j]; b=best[i-1][j+(1<<(i-1))]; if(RMQ[a]<RMQ[b]) best[i][j]=a; else best[i][j]=b; } return; } int askRMQ(int a,int b) { int t; t=mm[b-a+1];b-=(1<<t)-1; a=best[t][a];b=best[t][b]; return RMQ[a]<RMQ[b]?a:b; } int lcp(int a,int b) { int t; a=ranks[a];b=ranks[b]; if(a>b) {t=a;a=b;b=t;} return(height[askRMQ(a+1,b)]); } char st[maxn]; int str[maxn]; int sa[maxn]; int main(){ while(scanf("%s",st)!=EOF&&st[0]!='#'){ int n=strlen(st),m=0; for(int i=0;i<n;++i) { str[i]=st[i]-'a'+1; if(m<str[i]) m=str[i]; } str =0; da(str,sa,n+1,m+1); calheight(str,sa,n); ll ans=0; int minx,maxx; for(int i=1;i<=n/2;++i){ minx=1005;maxx=-1; for(int j=2;j<=n;++j){ if(height[j]>=i){ minx=min(minx,min(sa[j-1],sa[j])); maxx=max(maxx,max(sa[j-1],sa[j])); } else{ if(maxx-minx>=i) ans++; minx=1005;maxx=-1; } } if(maxx-minx>=i) ans++; } printf("%I64u\n",ans); } return 0; }
相关文章推荐
- 函数对象与仿函数(function object and functor)
- IE6 IE8下背景图片不显示问题
- 【POJ 3657】Haybale Guessing
- Leetcode -- Single Number
- 限制 root 远程登录的方法
- MyBatis传入多个参数的问题
- linux入门教程(七) linux系统用户以及用户组管理
- 蓝懿iOS零基础学习之旅 感谢刘国斌老师
- Win10使用高分辨率和大尺寸显示器字体模糊如何解决?
- JAVA获得当前tomcat的服务路径
- topcoder ExerciseMachine
- hdu 3853 概率dp
- objective-C编程 对象的类型和动态绑定摘要
- iOS coreData和MagicalRecord如何分页
- JavaScript 开发者必备的10款 SublimeText 插件
- 数据库索引
- java基本数据类型与包装类型
- 士兵突击
- 在Ubuntu(Linux)上安装Android Studio
- 开发前建议先写个文档,嗯想法不错