码迷,mamicode.com
首页 > 编程语言 > 详细

后缀数组

时间:2020-02-12 12:36:37      阅读:64      评论:0      收藏:0      [点我收藏+]

标签:pac   break   str   字符串   font   时间复杂度   文本   col   后缀   

后缀是从字符串的某个位置到字符串末尾的非空子串。例如:$suff(HORSE) = \{E, SE, RSE, ORSE, HORSE\}$。
后缀数组是包含字符串所有已排序后缀的数组。例如:$sa(CAMEL) = \{1-AMEL, 0-CAMEL, 3-EL, 4-L, 2-MEL\} = \{1, 0, 3, 4, 2\}$。
首先可以想出一种基于快速排序的后缀数组求法,但是时间复杂度为$O(n^2logn)$。可用一种倍增算法来优化,时间复杂度$O(nlogn)$,待补。

后缀数组用于事先不知道模板P的多模板匹配问题,此时需要处理文本串T。
sa是后缀排名到位置的映射
x是第一关键字位置到排名(数值)的映射
y是第二关键字排名到位置的映射
c是基数排序的桶

技术图片

 例题:洛谷P3809

#include<bits/stdc++.h>
using namespace std;

const int N = 1000050;
char s[N], p[N];
int sa[N], x[N], y[N], c[N], n;

void build_sa(int m) {
    n = strlen(s + 1);
    for(int i = 1; i <= n; i++) c[x[i] = s[i]]++;
    for(int i = 2; i <= m; i++) c[i] += c[i-1];
    for(int i = n; i >= 1; i--) sa[c[x[i]]--] = i;
    for(int k = 1; k <= n; k <<= 1) {
        int p = 1;
        for(int i = n - k + 1; i <= n; i++) y[p++] = i;
        for(int i = 1; i <= n; i++) if(sa[i] > k) y[p++] = sa[i] - k;
        for(int i = 1; i <= m; i++) c[i] = 0;
        for(int i = 1; i <= n; i++) c[x[i]]++;
        for(int i = 2; i <= m; i++) c[i] += c[i-1];
        for(int i = n; i >= 1; i--) sa[c[x[y[i]]]--] = y[i];
        swap(x, y);
        p = 1; x[sa[1]] = 1;
        for(int i = 2; i <= n; i++)
            x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p : ++p;
        if(p == n) break;
        m = p;
    }
}

int main() {
    gets(s + 1);
    build_sa(200);
    for(int i = 1; i <= n; i++) printf("%d ", sa[i]);
}

 

后缀数组

标签:pac   break   str   字符串   font   时间复杂度   文本   col   后缀   

原文地址:https://www.cnblogs.com/nioh/p/12298340.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!