浅谈后缀数组(对模板的理解
来源:互联网 发布:php workerman swoole 编辑:程序博客网 时间:2024/05/20 05:28
显然可知对于后缀数组最难理解的就是sa数组和rank数组的构建,而sa与rank数组之间有一个相互转化关系,这就必须理解sa数组和rank数组的含义,sa数组代表的是排名为i的后缀第一个字符所在的位置,而rank数组则表示的是第i个位置的后缀的排名;通过这个关系,我们可以实现sa与rank之间的转化,所以整个关键就成了如何去求他们其中的一个,根据,我的学习笔记来源这几个大神的博客可做参考:
1,http://blog.csdn.net/jokes000/article/details/7839686;
2,http://www.cnblogs.com/shanchuan04/p/5324009.html;前者具有深刻的代码分析及应用,后者更为形象的理解后缀数组;
下面之间贴上我自己对于后缀数组的理解:
#include<algorithm>#include<iostream>#include<queue>#include<stack>#include<vector>#include<set>#include<map>#include<cstdio>#include<cstring>#define MAXN 100005using namespace std;char a[MAXN];int rank[MAXN];int td[MAXN];int sa[MAXN];int Rank[MAXN];int txt[MAXN];int t1[MAXN];int t2[MAXN];int height[MAXN];int h[MAXN];bool cmp(int t[],int e,int w,int f){return t[e]==t[w]&&t[e+f]==t[w+f];}void Sa(char a[]){int *rank=t1;int *td=t2;int m=26;int len=strlen(a);for(int i=0;i<m;i++) txt[i]=0;for(int i=0;i<len;i++){rank[i]=a[i]-'a';txt[a[i]-'a']++;}
for(int i=1;i<m;i++) txt[i]+=txt[i-1];for(int i=len-1;i>=0;i--) sa[--(txt[a[i]-'a'])]=i;
//运用基数排序(计数排序)对于sa数组进行初始化sa;for(int k=1;k<=len;k*=2){int p;p=0;for(int i=len-k;i<len;i++) td[p++]=i;for(int i=0;i<len;i++){if(sa[i]>=k) td[p++]=sa[i]-k;}
//td数组表示的是第二关键字排名,详情见第二链接;for(int i=0;i<m;i++) txt[i]=0;for(int i=0;i<len;i++) txt[rank[td[i]]]++;for(int i=1;i<m;i++) txt[i]+=txt[i-1];for(int i=len-1;i>=0;i--) sa[--txt[rank[td[i]]]]=td[i];
//依照第一关键词的排序,复合第二关键词的顺序,进行排序更新sa数组;
//更新完sa数组后 就对rank数组进行更新,因为rank数组可能存在字符串相等的情况 即rank数组下不同的i可能对应相同的值所以必须对其离散化 也就是判断是否会存在相同的字符串
//运用第一关键词和第二关键词的二元组来进行离散swap(rank,td);rank[sa[0]]=0;p=0;for(int i=1;i<len;i++) rank[sa[i]]=cmp(td,sa[i-1],sa[i],k)?p:++p;if(p==len) return ;}return ;}void pd(char a[]){int len=strlen(a);for(int i=0;i<len;i++) Rank[sa[i]]=i;}void hh(char a[]){int len=strlen(a);h[sa[0]]=0;height[0]=0;for(int i=0;i<len;i++){int xx=Rank[i];int yy=sa[Rank[i]-1];int flag=0;if(Rank[i]==0) continue; int p=h[i-1]-1; int w=i; if(p<0){ p=0;}else{w+=p;yy+=p;} while(a[w]!='\0'&&a[yy]!='\0'){ if(a[w]==a[yy]) p++; else{ break; } w++;yy++; } h[i]=p; height[Rank[i]]=h[i];}
//hh函数是求height数组 即在排序后后缀的与前一个后缀的公共前缀的字符数
//关键运用对于i满足,h[i]>=h[i-1]-1;具体证明可以百度return ;}int main(){scanf("%s",a);Sa(a);for(int i=0;i<strlen(a);i++) cout<<sa[i]<<" ";cout<<endl;cout<<"Rank:"<<endl;pd(a);for(int i=0;i<strlen(a);i++) cout<<Rank[i]+1<<" ";cout<<endl;cout<<"Height:"<<endl;hh(a);for(int i=0;i<strlen(a);i++) cout<<height[i]<<" ";cout<<endl;}这算是这几天来的理解吧 在AC了一道模板题后 决定写下来这些心得 大致思路分析就是这样的还是需要多多刷题来巩固这些模板和思维
---- 眼界的宽度决定以后的成就
阅读全文
0 0
- 浅谈后缀数组(对模板的理解
- 后缀数组模板(理解)
- 后缀数组模板(详细理解)
- 【数据结构】后缀数组模板+代码理解
- 【后缀数组】后缀数组模板
- 【后缀数组】关于后缀数组模板的注解
- 【后缀数组】关于后缀数组模板的注解续
- [BZOJ1031]-[JSOI2007]字符加密Cipher-后缀数组模板(附自己的理解)
- yy浅谈后缀数组
- 浅谈后缀数组
- 后缀数组入门——初步理解及模板
- 浅谈对rss的理解
- 浅谈对Window的理解
- 浅谈对ActiveMQ的理解
- 浅谈对this的理解
- 浅谈对spring的理解
- 浅谈对spark的理解
- 浅谈对Context的理解
- 不论iPhone还是安卓,都可以这样恢复手机误删的文件
- 附件上传遇到的异常
- JDBC编程学习笔记(二)——执行SQL语句 ExecuteSQL.java
- 路由-回指路由
- HDU
- 浅谈后缀数组(对模板的理解
- linux下给mysql设置密码
- fl studio(水果音乐制作软件中文版) v12.4.2.33 官方中文版
- 消息队列应用场景
- Junit使用教程(三)
- 通话原理
- Intellij IDEA配置优化
- Monthly Expense--CSU-ACM2017暑假集训2-二分搜索
- 记住密码功能的制作