ImageVerifierCode 换一换
格式:DOCX , 页数:21 ,大小:21.88KB ,
资源ID:11608639      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/11608639.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(后缀数组题型讲解.docx)为本站会员(b****4)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

后缀数组题型讲解.docx

1、后缀数组题型讲解后缀数组、不重复子串 Distinct Substrings题目大意:给出一个字符串,问它的不重复子串有多少个。两题是一样的,除了字符串长度.分析:用后缀数组可以轻松解决。因为这个字符串的每个子串必然是某个后缀的前缀,先用后缀数组求出sa和height,那么对于sak,它有n-sak个子串,其中有heightk个是和上一个后缀重复的,所以要减去。所以用后缀数组求解的时间复杂度是O(n),后缀数组要是用倍增算法是O(nlog2n),效率很高。note:wa了一次,主要原因是忘了an=0这个关键的初值.PS:各位大牛对我的差劲的c+代码有什么看法可以尽管喷哈!codes:#incl

2、ude#includeusing namespace std;const long maxn=1010;long wnmaxn,wamaxn,wbmaxn,wvmaxn,amaxn,samaxn,rankmaxn,heightmaxn;char rmaxn;long cmp(long *r,long a,long b,long l) return ra=rb&ra+l=rb+l;void da(long *r,long *sa,long n,long m) long i,j,p,*x=wa,*y=wb,*t; for (i=0;im;i+) wni=0; for (i=0;in;i+) wnx

3、i=ri+; for (i=1;i=0;i-) sa-wnxi=i; for (p=1,j=1;pn;j*=2,m=p) for (p=0,i=n-j;in;i+) yp+=i; for (i=0;i=j) yp+=sai-j; for (i=0;im;i+) wni=0; for (i=0;in;i+) wnwvi=xyi+; for (i=1;i=0;i-) sa-wnwvi=yi; for (t=x,x=y,y=t,xsa0=0,p=1,i=1;in;i+) xsai=cmp(y,sai-1,sai,j)?p-1:p+; return;void calheight(long *r,lon

4、g *sa,long n) long i,j,k=0; for (i=1;i=n;i+) ranksai=i;heighti=0; for (i=0;i t; while (t-) cin r; long n=strlen(r); for (int i=0;in;i+) ai=static_cast(ri); an=0; da(a,sa,n+1,256); calheight(a,sa,n); long sum=0; for (i=1;i=n;i+) sum+=n-sai-heighti; cout sum =0;i-)以及cmp(y,sai-1,sai,j)。2、w数组理解错误,开小了- -

5、实际应该开maxn。结果re了一次.#include#includeusing namespace std;const int maxn=100010;int wmaxn,wamaxn,wbmaxn,wvmaxn,amaxn,samaxn,rankmaxn,heightmaxn;int cmp(int *r,int a,int b,int l) return ra=rb&ra+l=rb+l;void da(int *r,int *sa,int n,int m) int i,j,p,*x=wa,*y=wb,*t; for (i=0;im;i+) wi=0; for (i=0;in;i+) wxi

6、=ri+; for (i=1;i=0;i-) sa-wxi=i; for (p=1,j=1;pn;j*=2,m=p) for (p=0,i=n-j;in;i+) yp+=i; for (i=0;i=j) yp+=sai-j; for (i=0;im;i+) wi=0; for (i=0;in;i+) wwvi=xyi+; for (i=1;i=0;i-) sa-wwvi=yi; for (t=x,x=y,y=t,p=1,i=1,xsa0=0;in;i+) xsai=cmp(y,sai-1,sai,j)?p-1:p+; return;void cal(int *r,int *sa,int n)

7、int i,j,k=0; for (i=1;i=n;i+) ranksai=i; for (i=0;i t; while (t-) char smaxn; cin s; int n=strlen(s); for (i=0;in;i+) ai=static_cast(si); an=0; da(a,sa,n+1,255); cal(a,sa,n); int max=0,k=0; for (i=1;i=n;i+) if (maxheighti) max=heighti; k=sai; for (i=k,j=0;jmax;j+,i+) cout si; cout 0,而直接做差会使数组中的元素变成负

8、数,所以可以在做差后加上一个足够大的常数,来避免负数的出现。2、二分答案要写好很不容易。我现在还有点糊涂- -3、输入用scanf。题目里也有这个提示.codes:#includeusing namespace std;const int maxn=20010;int wmaxn,wamaxn,wbmaxn,wvmaxn,amaxn,xmaxn,samaxn,rankmaxn,heightmaxn,n;int cmp(int *r,int a,int b,int l) return ra=rb&ra+l=rb+l;void da(int *r,int *sa,int n,int m) int

9、i,j,p,*x=wa,*y=wb,*t; for (i=0;im;i+) wi=0; for (i=0;in;i+) wxi=ri+; for (i=1;i=0;i-) sa-wxi=i; for (p=1,j=1;pn;j*=2,m=p) for (p=0,i=n-j;in;i+) yp+=i; for (i=0;i=j) yp+=sai-j; for (i=0;im;i+) wi=0; for (i=0;in;i+) wwvi=xyi+; for (i=1;i=0;i-) sa-wwvi=yi; for (t=x,x=y,y=t,p=1,i=1,xsa0=0;in;i+) xsai=cm

10、p(y,sai-1,sai,j)?p-1:p+; return;void cal(int *r,int *sa,int n) int i,j,k=0; for (i=1;i=n;i+) ranksai=i; for (i=0;in;heightranki+=k) for (k?k-:0,j=saranki-1;ri+k=rj+k;k+); return;int check(int k) int max=0,min=maxn; for (int i=1;i=n;i+) if (heightisai?max:sai; min=min=k) return 1; if (max-min=k) retu

11、rn 1; else return 0;int Bin_search(int l,int r) int mid; for (mid=(l+r)1;l1) if (check(mid) l=mid+1; else r=mid-1; if (check(mid) return mid; else return 0; int main() scanf(%d,&n); while (n) int i,k; for (i=0;in;i+) scanf(%d,&xi); a0=500; for (i=1;in;i+) ai=xi-xi-1+100; an=0; da(a,sa,n+1,501); cal(

12、a,sa,n); k=Bin_search(0,n/2)+1; if (k5) k=0; printf(%dn,k); scanf(%d,&n); return 0; -后缀数组、出现k次的重复子串题目大意:给出n个数字组成的一个字符串,求最长的恰好出现k次的重复子串(可重叠)的字符串的长度。分析:后缀数组一个经典的应用。先二分答案,然后分组。只要某一组包含的后缀数量大于等于k,表示有解。这个不难理解。等完成了论文里面的练习之后,我再写个总结笔记吧。深刻体会到后缀数组的强大.note:1、分组时,每次heightik时,第i个后缀是归到下一个组中的。 2、scanf()返回的值是成功读取了多少

13、个数据,如果文件结束了,返回EOF。一开始不知道这个,结果OLE= =codes:#includeusing namespace std;const int maxn=20010;int wmaxn*2,wamaxn,wbmaxn,wvmaxn,samaxn,rankmaxn,heightmaxn,amaxn;int n,m,k;int cmp(int *r,int a,int b,int l) return ra=rb&ra+l=rb+l;void da(int *r,int *sa,int n,int m) int i,j,p,*x=wa,*y=wb,*t; for (i=0;im;i+)

14、 wi=0; for (i=0;in;i+) wxi=ri+; for (i=1;i=0;i-) sa-wxi=i; for (p=1,j=1;pn;j*=2,m=p) for (i=n-j,p=0;in;i+) yp+=i; for (i=0;i=j) yp+=sai-j; for (i=0;im;i+) wi=0; for (i=0;in;i+) wwvi=xyi+; for (i=1;i=0;i-) sa-wwvi=yi; for (t=x,x=y,y=t,xsa0=0,p=1,i=1;in;i+) xsai=cmp(y,sai-1,sai,j)?p-1:p+; return; void

15、 cal(int *r,int *sa,int n) int i,j,k=0; for (i=1;i=n;i+) ranksai=i; for (i=0;in;heightranki+=k) for (k?k-:0,j=saranki-1;ri+k=rj+k;k+); return; int check(int x) int i,cnt; for (i=1;i=n;i+) if (heighti=k) return 1; if (cnt=k) return 1; return 0; int bin_search(int l,int r) int mid; for (mid=(r+l)1;l1)

16、 if (check(mid) l=mid+1; else r=mid-1; return mid;int main() int i; while (scanf(%d %d,&n,&k)!=EOF) m=0; for (i=0;iai?m:ai; an=0; m+; da(a,sa,n+1,m); cal(a,sa,n); int k=bin_search(0,n); printf(%dn,k); return 0; -后缀数组、最长回文子串题目大意:给出一个字符串,求它的最长回文子串。分析:这题数据规模不大(n=1000),所以直接暴力可以解决。不过如果数据规模大了,暴力就不行了。这里介绍后

17、缀数组的做法。首先,枚举回文子串的中心所在位置。这里要分回文串长度为奇数和偶数两种情况考虑。这两个问题均可以转化为求一个后缀和一个倒着写的后缀的最长公共前缀。具体地,将原串与反着写之后的原串相连,中间以一个特殊字符隔开。这个特殊字符只要不是0号,不影响后缀的排序,就没有问题。(不能是0是因为我的倍增算法要求除了字符串的最后一位以外,其它位不能为0,否则会出错)然后算出height数组。两个后缀的最长公共前缀为两个后缀排序之后,它们之间的串的height值的最小值。这个可以自己举个具体例子好好体会。用st算法求解rmq问题即可。notes:1、st算法我写得实在是少- -for循环的先后要注意,

18、先循环j,再循环i。 2、我在写的时候,加了一个错误的判断条件,结果导致wa on test 22,以后加啥代码都要有严谨的逻辑才好加.codes:#include#include#includeusing namespace std;const int maxn=2010;int n,wmaxn,wamaxn,wbmaxn,wvmaxn,amaxn,samaxn,rankmaxn,heightmaxn,fmaxn20;int cmp(int *r,int a,int b,int l) return ra=rb&ra+l=rb+l;void da(int *r,int *sa,int n,in

19、t m) int i,j,p,*x=wa,*y=wb,*t; for (i=0;im;i+) wi=0; for (i=0;in;i+) wxi=ri+; for (i=1;i=0;i-) sa-wxi=i; for (p=1,j=1;pn;m=p) for (p=0,i=n-j;in;i+) yp+=i; for (i=0;i=j) yp+=sai-j; for (i=0;im;i+) wi=0; for (i=0;in;i+) wwvi=xyi+; for (i=1;i=0;i-) sa-wwvi=yi; for (t=x,x=y,y=t,p=1,xsa0=0,i=1;in;i+) xsa

20、i=cmp(y,sai-1,sai,j)?p-1:p+; return;void cal(int *r,int *sa,int n) int i,j,k=0; for (i=1;i=n;i+) ranksai=i; for (i=0;ib) return a; else return b;int nmin(int a,int b) if (ab) return a; else return b;void rmq(int *rank,int n) int i,j; memset(f,127,sizeof(f); for (i=1;i=n;i+) fi0=heighti; for (j=1;j20;j+) for (i=1;i+(1j)-1=n;i+) fij=nmin(fij-1,f(1b) int t=a; a=b; b=t; a+; int t=int(log(double(b-a+1)/log(2.00); return nmin(fat,fb-(1t)+1t);int main() char smaxn; cin

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1