后缀数组倍增算法代码及解释
来源:互联网 发布:淘宝your highness 编辑:程序博客网 时间:2024/05/22 05:23
经历
最近在学习后缀数组,我发现后缀数组那20多行代码10多个for,真的是太抽象了,基数排序又不是很会所以学起来异常艰难,在冥思苦想以及抱神犇(Dumpling)的大腿后终于有些理解了,将自己写的注释发出来帮助和我一样的人= =.(我觉得我对代码的讲解还是比较细了,但是我没有讲方法,只讲了代码,方法应该比较好懂.)
讲解
#include<queue>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int maxn=15000+10;const char msg[]="ABCDEFG";char s[maxn];int sa[maxn],t[maxn],t2[maxn],c[maxn],n;void build(int m){ int i,*x=t,*y=t2; for(i=0;i<m;i++) c[i]=0; for(i=0;i<n;i++) c[x[i]=s[i]]++; for(i=1;i<m;i++) c[i] += c[i-1]; for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i; /* 解读:c[x[i]]表示字符串中<=i的字符个数,那么i应该在第 c[x[i]]个(同字符并不影响),因为sa从0开始,所以名次减 一,但将这个拿走之后会少一个字符,c[x[i]]要-1,所以直接 -- .即这一趟按单个字母排 . */ for(int k=1;k<n;k<<=1) { //倍增,将k凑成k*2长度,k>=n就没必要了 int p=0; for(i=n-1;i>=n-k;i--) y[p++]=i; /* #define 第一关键字 G1 #define 第二关键字 G2 这是一些长度不够的后缀,G2排序时一定会排 在前面(G2全为'\0'(因为有'全'所以是n-k 而不是n-k*2+1,倍增出来的G2是经过合并的)) 这里将n-k到n-1放进了y数组 */ for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k; /* 合并过程中需要将G2往前移k个位置,那么y (现在是按G2在排)中,y中G2的相对排名和原来的G2是一 样的,所以直接复制过来,(也可以理解为sa并没 有提供n-k~n-1这一段的有效信息,因为G2是空的) 这里将0~n-k-1放进了y数组 综上,这两行将0~n-1不重不漏的放进了y数组. */ for(i=0;i<m;i++) c[i]=0; for(i=0;i<n;i++) c[x[y[i]]]++; for(i=1;i<m;i++) c[i]+=c[i-1]; for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; /* 这4行对G2已经排好序的y进行G1排序,仍然是基数 排序,不过因为G2变了(排单个字母时也可理解为 G2全为空),不能再用i而要用y[i],想一想如果G2 全空的话无论什么顺序都可以. 之所以要倒着加是保证按照G2已经排好的顺序, 因为c[x[y[i]]]是相同G1里面名次最大的那个 QAQ我终于懂了 */ swap(x,y); p=1;x[sa[0]]=0;//sa[0]是编号最小的那个后缀 for(i=1;i<n;i++) if(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]) //G1==G'1&&G2==G'2 x[sa[i]]=p-1; else x[sa[i]]=p++; if(p>=n) break; m=p; } return ;}void debug(){ for(int i=0;i<n;i++) { printf("%d ",i); for(int j=sa[i];j<n;j++) { printf("%c",s[j]); } printf("\n"); } return ;}int main(){ scanf("%s",s); n=strlen(s); build('}'+1); debug(); return 0;}
1 0
- 后缀数组倍增算法代码及解释
- 后缀数组 倍增算法 代码详解
- 后缀数组 倍增算法
- 后缀数组,倍增算法
- 倍增算法实现后缀数组
- 后缀数组之倍增算法
- 后缀数组倍增算法模版
- 后缀数组之倍增算法
- 后缀数组 倍增算法模板
- 后缀数组 倍增算法详解
- 后缀数组学习笔记——罗穗骞倍增算法代码
- 后缀数组学习笔记——罗穗骞倍增算法代码
- 后缀数组学习笔记——罗穗骞倍增算法代码
- 后缀数组学习笔记——罗穗骞倍增算法代码
- 后缀数组——罗穗骞倍增算法代码详解
- 倍增算法求解字符串的后缀数组
- 后缀数组,Manber & Mayer 倍增算法
- 后缀数组 (由倍增算法构造)
- linux私房菜学习笔记—vim编辑器
- hdu 1392(求凸包周长)
- 灵活式的collectionview的header
- 能PIN通对方,对方却ping不通本机的问题
- iOS 延迟执行的方法总结
- 后缀数组倍增算法代码及解释
- Ubuntu解决MyEclipse/Eclipse Ctrl+Alt+Up/Down无法使用的问题
- Redis----sorted set数据类型操作
- js反选
- WikiTaxi_Importer_1.3.1 维基 离线数据库
- 或许我们做错了,但绝非一无是处
- beego的文档生成
- Js操作Select大全(取值、设置选中等等)
- Android4.4起ART虚拟机代替dalivk虚拟机