后缀排序 后缀自动机的应用

原创 2016年08月31日 13:57:34

同步个人博客 http://sxysxy.org/blogs/23 到csdn)

给一字符串的所有后缀排个序输出,字符串长度 <= 100000

排序要求字典序小的在前面,在满足这个条件的情况下,短的后缀放到前面

例如ababa的后缀排序结果是[a, aba, ababa, ba, baba]。

暴力做法很容易想到,枚举出字符串s的总共length(s)个后缀,sort一下,然而time limit exceed (

把后缀都插入字典树? time limit exceed & memory limit exceed。

所以这个时候就需要后缀自动机登场了。

后缀排序可以看作是给字符串所有子串排序的一个特殊情况,就是子串的右端点是字符串的末尾。

对与子串的排序,我们可以构造完后缀自动机然后dfs,每次先走字典序小的字符,最后遍历完毕就是子串排序的结果。

只排序后缀呢?

今天上午英语课上我手画了一个字符串的后缀自动机然后脑补出来了一个这样的方法:

我们从后缀自动机最后一个状态St出发,向上走后缀链接树(也有叫”parent树”的),途经的状态节点可以接受的最长的字符串都是St可接受的最长的字符串的后缀。而St可接受的最长的字符串恰好就是整个字符串str(因为St是最后一个状态)。也就是说,从St出发走后缀链接一直到顶,恰好可以途径字符串str的所有后缀。

那么后缀排序就可以把从St出发走后缀链接到顶途径的所有节点都标记一下,之后像子串排序一样dfs这个后缀自动机,只在打了标记的点那里输出,就可以得到后缀排序的结果了。最后总的时间复杂度还是O(n),SAM很强啊!!!

这里写图片描述

代码

#include <cstdio>
#include <cstring>
#include <cstdarg>
#include <algorithm>
#include <vector>
using namespace std;
const int MAXN = 1e6+2;
const int SIGMA = 26;
const int BASE = (int)'a';
class SAM
{
    public:
    int last, size;
    struct state
    {
        int link, len;
        int next[SIGMA];
        bool mark;
        void init()
        {
            link = -1;
            len = 0;
            mark = false;
            memset(next, 0, sizeof(next));
        }
    }st[MAXN<<1];
    int newst()
    {
        st[size++].init();
        return size-1;
    }
    SAM()
    {
        last = size = 0;
        newst();
    }
    void expand(char newc)
    {
        int c = newc-BASE;
        int cur = newst();
        st[cur].len = st[last].len+1;
        int p;
        for(p = last; p != -1 && !st[p].next[c]; p = st[p].link)
            st[p].next[c] = cur;
        if(p == -1)
            st[cur].link = 0;
        else
        {
            int q = st[p].next[c];
            if(st[q].len == st[p].len + 1)
                st[cur].link = q;
            else
            {
                int clone = newst();
                st[clone].len = st[p].len + 1;
                st[clone].link = st[q].link;
                memcpy(st[clone].next, st[q].next, sizeof(st[q].next));
                for(; p != -1 && st[p].next[c] == q; p = st[p].link)
                    st[p].next[c] = clone;
                st[q].link = st[cur].link = clone;
            }
        }
        last = cur;
    }
    char buf[MAXN];
    int top;
    void dfs(int u)
    {
        if(top && st[u].mark)puts(buf);
        state &cur = st[u];
        for(int i = 0; i < SIGMA; i++)
        {
            if(cur.next[i])
            {
                buf[top++] = i+BASE;
                buf[top] = 0;
                dfs(cur.next[i]);
                top--;
            }
        }
    }
    void suffix_sort()
    {
        top = 0;
            //从最后一个状态开始,走后缀链接到顶,途径节点打上标记。
        for(int p = last; p; p = st[p].link)
            st[p].mark = true;
        dfs(0);
    }
}sam;

int main()
{
    char c;
    while(c = getchar())
        if(c >= 'a' && c <= 'z')break;
    sam.expand(c);
    while(c = getchar())
        if(c >= 'a' && c <= 'z')sam.expand(c);
            else break;
    sam.suffix_sort();
    return 0;
}
版权声明:本文为博主原创文章,允许转载请保留原作者信息:sxysxy 举报

相关文章推荐

后缀排序 后缀自动机的应用

同步个人博客 http://sxysxy.org/blogs/23 到csdn)给一字符串的所有后缀排个序输出,字符串长度 <= 100000排序要求字典序小的在前面,在满足这个条件的情况下,短的后...

后缀自动机

应用简便起见,我们假设字母表的大小k为常数。存在性查询问题.给定文本T,询问格式如下:给定字符串P,问P是否是T的子串。复杂度要求.预处理O(length(T)),每次询问O(P)。算法.我们对文本T...

精选:深入理解 Docker 内部原理及网络配置

网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

后缀自动机

如果我们想要建立一个自动机,使它能够接收一个串s的所有后缀,那么最暴力的想法应该就是,直接用这个串的所有后缀来建立一个AC自动机 上面就是用aabbabd这个字母串作为母串建立的AC自动...

后缀自动机

后缀自动机学习(复习)笔记

后缀自动机

ACM模版后缀自动机const int CHAR = 26; const int MAXN = 250010;struct SAM_Node { SAM_Node *fa, *next[CHA...
  • f_zyj
  • f_zyj
  • 2016-07-12 19:20
  • 652

后缀自动机

#include #include #include #include #include using namespace std; const int maxn=1e6; struct code{ ...

后缀自动机

后缀数组虽然强大,后缀自动机也不可忽视,而且后缀自动机有它独特的特点,对于某些题目可能更得心应手; 什么是后缀自动机,他处于什么目的的数据结构,他为什么能省时? 假如我们把一个长度为len的字符串...

后缀自动机

spoj1811 #include #include #include #include using namespace std; #define maxn 510000 struct Auto...

后缀自动机

首先补一点自动机的知识, 有状态集合,字符集,初始状态,终止状态和状态转移,反正我是学了AC自动机才理解这些东西的。 当时Clj讲的时候,感觉很快,各种概念没有跟上来,现在回头弄一弄。 ...

hdu 4436 str2int (后缀自动机)

hdu 4436 str2int (后缀自动机) 题意:给出n个数字,数字很长,用字符串读入,长度总和为10^5。求这n个字符串的所有子串(不重复)的和取模2012 。 解题思路:后缀自动机。。因...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)