后缀数组模板

#include <set>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define maxn 1100000
using namespace std;
const int MAXN = 500;
char s[MAXN];
int sa[MAXN];//后缀数组 suffix array 所有的后缀排序后的结果 即排第几的是谁
//rank是你排第几
int t[MAXN];
int t2[MAXN];
int c[MAXN];
int n;
//构造字符s的后缀数组。每个字符值必须为 0 ~ m - 1
void build_sa(int m)
{
    int i;
    int *x = t;
    int *y = t2;
    //对所有后缀的第一个字符排序,得到后缀第一个字符的sa
    for (i = 0; i < m; i++) //清0
        c[i] = 0;
    for (i = 0; i < n; i++) //统计s中每个字符出现的次数,保存在c中
        c[ x[i] = s[i] ]++; //将s赋值给x
    for (i = 1; i < m; i++) //小于等于 字符i 的字符有多少个
        c[i] += c[i - 1];
    for (i = n - 1; i >= 0; i--) //最后一个后缀往前
        sa[ --c[x[i]] ] = i;

    for (int k = 1; k <= n; k <<= 1)//log(n)次排序
    {
        int p = 0;
        //排序第二关键值,对第二关键值得排序结果可以利用上一次求得的sa直接算出
        for (i = n - k; i < n; i++) //k是当前字符串的长度
            y[p++] = i;
        for (i = 0; i < n; i++) 
            if (sa[i] >= k) 
                y[p++] = sa[i] - k;//y保存对第二关键值排序的结果 
        //基数排序第一关键值
        for (i = 0; i < m; i++) //清0
            c[i] = 0;
        for (i = 0; i < n; i++) 
            c[ x[ y[i] ] ]++;
        for (i = 0; i < m; i++) 
            c[i] += c[i - 1];
        for (i = n - 1; i >= 0; i--) 
            sa[ --c[x[y[i]]] ] = y[i];
        //根据sa和y数组计算新的x数组
        swap(x, y);
        p = 1; x[sa[0]] = 0;
        for (i = 1; i < n; i++)
            x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++;
        if (p >= n)
            break;
        m = p;
    }
}

int main() 
{

    return 0;
}

你可能感兴趣的:(后缀数组模板)