`
暴风雪
  • 浏览: 389017 次
  • 性别: Icon_minigender_2
  • 来自: 杭州
社区版块
存档分类
最新评论

后缀数组倍增算法模版

阅读更多

   首先献上模版

 

#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
2
0
分享到:
评论
4 楼 lhshaoren 2012-09-19  
主要为了方便后面求height[]的操作。for(k ? k -- : 0, j = sa[rank[i]-1]; r[i+k] == r[j+k]; k ++);  避免这句中rank[i]-1出现为负数的情况
3 楼 a402630999 2012-06-01  
偶是 菜鸟啊。。
2 楼 暴风雪 2012-05-15  
a402630999 写道
膜拜 宇神!

Orz 你是?
1 楼 a402630999 2012-05-14  
膜拜 宇神!

相关推荐

    Alone_L模板1

    其中,倍增算法(Doubly-Approximate Algorithm,简称DA)是一种常用的构建后缀数组的方法。在给定的代码中,`da`函数就是用来实现这一算法的。该算法的基本思想是通过分治策略将问题规模逐渐减小,直至解决问题。 ...

    ACM算法模板和pku代码

    后缀数组 倍增算法 基于多串匹配的有限状态自动机 未分类 归并排序 星期几的计算 N皇后构造法 几个常用的位操作 最大最小定理总结 0/1分数规划总结 (by yxysdcl 2008/11/19) 代码目录结构: 目录: 动态规划...

    ACM/ICPC模板

    --后缀数组(倍增实现) --手工vector类 --线段树的几个模板 数学相关 --高斯消元(用double ,c++实现) --高斯消元(用bigInteger和分数类 ,Java实现) //thanks to love8909 --矩阵运算 --欧拉函数 --初等数论(模线性...

    kuangbin acm模板超级好用

    1.5 后缀数组 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.5.1 DA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.5.2 DC3 . . . ...

    吉大acm模板

    - 使用Manber-Myers算法或DC3算法构建后缀数组。 ##### 3.7 RMQ离线算法(Offline Range Minimum Query) - **定义**: 预处理后能够快速查询数组区间最小值的算法。 - **应用场景**: 数组区间查询等。 - **算法步骤*...

    中山大学ACM模板 中山大学 ACM 模板

    - **实现细节**:可以使用预处理数组的方式,结合倍增算法来求解LCA问题;对于RMQ问题,可以使用线段树或稀疏表。 #### 8.2 FFT - **功能描述**:实现一种快速傅立叶变换算法。 - **实现细节**:通过递归将大问题...

    经典算法源代码(for ACM)

    **最短公共祖先(两个长字符串/多个短字符串)**:通过构建后缀数组或使用字符串散列等方法,快速求解最短公共祖先问题。 #### Geometry 计算几何 **GRAHAM**:Graham扫描算法是求凸包的经典算法之一,它通过维护...

    九野的模版3.15.10.pdf

    - **后缀数组**:用于高效地处理字符串的各种操作,如字符串查找、最长重复子串等问题。 ### 数论 - **自适应辛普森公式**:数值积分的一种方法。 - **高斯消元**:求解线性方程组的基本方法之一,包括浮点数解和...

    6、省选+NOI-第六部分 技巧与思想_2020.08.27.pdf

    - **倍增算法**:用于快速计算某些问题,如计算LCA(最近公共祖先)。 - **构造**:创建特定结构或序列以满足问题需求。 - **高精度运算**:处理超过标准类型所能表示的大整数。 - **模拟**:按照问题规则进行...

    leetcode答案-leetcode:一个星期日穿leetcode

    基础技巧:分治、倍增、二分、贪心 数据结构 - Data Structures 数组与链表:单 / 双向链表、跳舞链 栈与队列 树与图:最近公共祖先、并查集 哈希表 堆:大 / 小根堆、可并堆 字符串:字典树、后缀树 递归模板 ...

Global site tag (gtag.js) - Google Analytics