• 后缀数组模板


    引用自HH大牛的模板

    http://www.notonlysuccess.com/index.php/sa/

    // File Name: suffix.cpp
    // Author: Zlbing
    // Created Time: 2013年09月04日 星期三 19时57分46秒
    
    #include<iostream>
    #include<string>
    #include<algorithm>
    #include<cstdlib>
    #include<cstdio>
    #include<set>
    #include<map>
    #include<vector>
    #include<cstring>
    #include<stack>
    #include<cmath>
    #include<queue>
    using namespace std;
    #define CL(x,v); memset(x,v,sizeof(x));
    #define INF 0x3f3f3f3f
    #define LL long long
    #define REP(i,r,n) for(int i=r;i<=n;i++)
    #define RREP(i,n,r) for(int i=n;i>=r;i--)
    //rank从0开始
    //sa从1开始,因为最后一个字符(最小的)排在第0位
    //height从2开始,因为表示的是sa[i-1]和sa[i]
    const int MAXN=220000;
    int rank[MAXN],sa[MAXN],X[MAXN],Y[MAXN],height[MAXN],s[MAXN];
    int buc[MAXN];
    void calheight(int n) {
        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] ; s[i+k] == s[j+k] ; k++);
    }
    bool cmp(int *r,int a,int b,int l) {
        return (r[a] == r[b] && r[a+l] == r[b+l]);
    }
    void suffix(int n,int m = 128) {
        int i , l , p , *x = X , *y = Y;
        for(i = 0 ; i < m ; i ++) buc[i] = 0;
        for(i = 0 ; i < n ; i ++) buc[ x[i] = s[i]  ] ++;
        for(i = 1 ; i < m ; i ++) buc[i] += buc[i-1];
        for(i = n - 1; i >= 0 ; i --) sa[ --buc[ x[i] ]] = i;
        for(l = 1,p = 1 ; p < n ; m = p , l *= 2) {
            p = 0;
            for(i = n-l ; i < n ; i ++) y[p++] = i;
            for(i = 0 ; i < n ; i ++) if(sa[i] >= l) y[p++] = sa[i] - l;
            for(i = 0 ; i < m ; i ++) buc[i] = 0;
            for(i = 0 ; i < n ; i ++) buc[ x[y[i]] ] ++;
            for(i = 1 ; i < m ; i ++) buc[i] += buc[i-1];
            for(i = n - 1; i >= 0 ; i --) sa[ --buc[ x[y[i]] ] ] = y[i];
            for(swap(x,y) , x[sa[0]] = 0 , i = 1 , p = 1 ; i < n ; i ++)
                x[ sa[i] ] = cmp(y,sa[i-1],sa[i],l) ? p-1 : p++;
        }
        calheight(n-1);//后缀数组关键是求出height,所以求sa的时候顺便把rank和height求出来
    }
    //当需要反复询问两个后缀的最长公共前缀时用到RMAXNQ
    int Log[MAXN];
    int best[20][MAXN];
    void initRMQ(int n) {//初始化RMQ
        for(int i = 1; i <= n ; i ++) best[0][i] = height[i];
        for(int i = 1; i <= Log[n] ; i ++) {
            int limit = n - (1<<i) + 1;
            for(int j = 1; j <= limit ; j ++) {
                best[i][j] = min(best[i-1][j] , best[i-1][j+(1<<i>>1)]);
            }
        }
    }
    int lcp(int a,int b) {//询问a,b后缀的最长公共前缀
        a = rank[a];    b = rank[b];
        if(a > b) swap(a,b);
        a ++;
        int t = Log[b - a + 1];
        return min(best[t][a] , best[t][b - (1<<t) + 1]);
    }
    int main() {
        //预处理每个数字的Log值,常数优化,用于RMQ
        Log[0] = -1;
        for(int i = 1; i < MAXN ; i ++) {
            Log[i] = (i&(i-1)) ? Log[i-1] : Log[i-1] + 1 ;
        }
        //*******************************************
        //    n为数组长度,下标0开始
        //    将初始数据,保存在s里,并且保证每个数字都比0大
        //    m = max{ s[i] } + 1
        //    一般情况下大多是字符操作,所以128足够了
        //*******************************************
        s[n] = 0;
        suffix(n+1,m);
        initRMQ(n);
    
        return 0;
    }
  • 相关阅读:
    matlab的两种函数简单使用介绍
    有关水晶易表的使用
    有关navicat11版本的破解
    关于配置javaee过程中的问题
    svn在服务器配置安装过程中的问题
    数据挖掘一
    javaee版eclipse导包出现未找到类问题
    git常用命名行总结
    学习kafka的基本信息总结
    JQuery之事件冒泡
  • 原文地址:https://www.cnblogs.com/arbitrary/p/3304289.html
Copyright © 2020-2023  润新知