首先献上模版
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int Max = 20001;
int num[Max];
int sa[Max], rank[Max], height[Max];
int wa[Max], wb[Max], wv[Max], wd[Max];
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 n, int m){ // 倍增算法 r为待匹配数组 n为总长度 m为字符范围
int i, j, p, *x = wa, *y = wb, *t;
for(i = 0; i < m; i ++) wd[i] = 0;
for(i = 0; i < n; i ++) wd[x[i]=r[i]] ++;
for(i = 1; i < m; i ++) wd[i] += wd[i-1];
for(i = n-1; i >= 0; i --) sa[-- wd[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 ++) wd[i] = 0;
for(i = 0; i < n; i ++) wd[wv[i]] ++;
for(i = 1; i < m; i ++) wd[i] += wd[i-1];
for(i = n-1; i >= 0; i --) sa[-- wd[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 ++;
}
}
}
void calHeight(int *r, int n){ // 求height数组。
int i, j, k = 0;
for(i = 1; i <= n; i ++) rank[sa[i]] = i;
for(i = 0; i < n; height[rank[i ++]] = k){
for(k ? k -- : 0, j = sa[rank[i]-1]; r[i+k] == r[j+k]; k ++);
}
}
int main(){
char str[Max];
int i, m=30, ans,len;
while(scanf("%s",str)!=EOF){
len=strlen(str);
for(i=0;i<=len;i++)num[i]=str[i]-'a'+1;
num[len]=0;
da(num, len + 1, m);
calHeight(num, len);
printf("num: \n");
for(i=0;i<=len;i++){printf("%d ",num[i]);}printf("\n");
printf("sa: \n");
for(i=0;i<=len;i++){printf("%d ",sa[i]);}printf("\n");
printf("rank: \n");
for(i=0;i<=len;i++){printf("%d ",rank[i]);}printf("\n");
printf("height: \n");
for(i=0;i<=len;i++){printf("%d ",height[i]);}printf("\n");
}
return 0;
}
一直不清楚为什么要在最后要加上后缀0,希望有大神解释呃Orz。
这里num[0~n-1]为有效值 就是输入的字符串稍稍转化而成的数组
sa[1~~n]为有效值 sa[i]=a则代表排在第 i 位的是第a个后缀。 a属于[0~~n-1]
rank[0~~n-1]是有效值 rank[i]=b则代表第 i 个后缀排在第b位 b属于[1~~n]
height[2~~n]是有效值 height[i]=c 则代表排在第 i 位的后缀和排在第i-1的后缀的最长前缀长度是c。
- 大小: 10.8 KB
分享到:
相关推荐
其中,倍增算法(Doubly-Approximate Algorithm,简称DA)是一种常用的构建后缀数组的方法。在给定的代码中,`da`函数就是用来实现这一算法的。该算法的基本思想是通过分治策略将问题规模逐渐减小,直至解决问题。 ...
后缀数组 倍增算法 基于多串匹配的有限状态自动机 未分类 归并排序 星期几的计算 N皇后构造法 几个常用的位操作 最大最小定理总结 0/1分数规划总结 (by yxysdcl 2008/11/19) 代码目录结构: 目录: 动态规划...
--后缀数组(倍增实现) --手工vector类 --线段树的几个模板 数学相关 --高斯消元(用double ,c++实现) --高斯消元(用bigInteger和分数类 ,Java实现) //thanks to love8909 --矩阵运算 --欧拉函数 --初等数论(模线性...
1.5 后缀数组 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.5.1 DA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.5.2 DC3 . . . ...
- 使用Manber-Myers算法或DC3算法构建后缀数组。 ##### 3.7 RMQ离线算法(Offline Range Minimum Query) - **定义**: 预处理后能够快速查询数组区间最小值的算法。 - **应用场景**: 数组区间查询等。 - **算法步骤*...
- **实现细节**:可以使用预处理数组的方式,结合倍增算法来求解LCA问题;对于RMQ问题,可以使用线段树或稀疏表。 #### 8.2 FFT - **功能描述**:实现一种快速傅立叶变换算法。 - **实现细节**:通过递归将大问题...
**最短公共祖先(两个长字符串/多个短字符串)**:通过构建后缀数组或使用字符串散列等方法,快速求解最短公共祖先问题。 #### Geometry 计算几何 **GRAHAM**:Graham扫描算法是求凸包的经典算法之一,它通过维护...
- **后缀数组**:用于高效地处理字符串的各种操作,如字符串查找、最长重复子串等问题。 ### 数论 - **自适应辛普森公式**:数值积分的一种方法。 - **高斯消元**:求解线性方程组的基本方法之一,包括浮点数解和...
- **倍增算法**:用于快速计算某些问题,如计算LCA(最近公共祖先)。 - **构造**:创建特定结构或序列以满足问题需求。 - **高精度运算**:处理超过标准类型所能表示的大整数。 - **模拟**:按照问题规则进行...
基础技巧:分治、倍增、二分、贪心 数据结构 - Data Structures 数组与链表:单 / 双向链表、跳舞链 栈与队列 树与图:最近公共祖先、并查集 哈希表 堆:大 / 小根堆、可并堆 字符串:字典树、后缀树 递归模板 ...