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

算法学习:后缀自动机

时间:2019-09-11 21:47:47      阅读:113      评论:0      收藏:0      [点我收藏+]

标签:字母   不同的   解决问题   space   algo   top   queue   mem   pre   

【前置知识】

AC自动机(没有什么关联,但是看懂了会对后缀自动机有不同的理解)

 

【解决问题】

各种子串的问题

 

 

【算法学习】

学习后缀自动机的过程中,看到了许多相关性质和证明,但是奈何才疏学浅(lan)

暂时先放着,到有空再更

 

【算法分析】

后缀自动机和AC自动机和回文自动机的不同点在于

后缀自动机是个DAG,而AC自动机和回文自动机是

 

 

首先理解   endpos 数组,每个子串都有一个endpos数组,表示他在字符串中出现的位置的结束位置

而endpos数组相同的子串,就被称为endpos类

而显然易见的,endpos类中最长的子串,能够在子类中找到他的所有子串

而后缀自动机中的节点,就是endpos类,所代表的字符串,也可以表示为这个endpos类中最长的子串

 

节点之间的边,是互相之间的字母

通过字母走到节点,能够得到关于这个节点子串的后缀

即此节点所代表的整个 endpos 类

 

 

 

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define ll long long
using namespace std;
const int MAXN = 2*1e6 + 10;
const int CHAR = 27;
struct note
{
    int ch[CHAR];
    int fa;
    ll len;
}dian[MAXN];
int zhi[MAXN];
int cnt=1, now=1;
char s[MAXN];
void insert(int c)
{
    int p = now, np = now = ++cnt; zhi[cnt] = 1;
    dian[np].len = dian[p].len + 1;
    for (;p && !dian[p].ch[c]; p = dian[p].fa) 
        dian[p].ch[c] = np;
    if (!p) dian[np].fa = 1;
    else
    {
        int q = dian[p].ch[c];
        if (dian[q].len == dian[p].len + 1) dian[np].fa = q;
        else
        {
            int nq = ++cnt;
            dian[nq] = dian[q];
            dian[nq].len = dian[p].len + 1;
            dian[q].fa = dian[np].fa = nq;
            for (; p && dian[p].ch[c] == q; p = dian[p].fa)
                dian[p].ch[c] = nq;
        }
    }
}
ll ans = 0;
int cd;
int st[MAXN],top;
struct NOTE
{
    int to;
    int nt;
}edge[MAXN];
void add(int x, int y)
{
    top++; edge[top].nt = st[x]; edge[top].to = y; st[x] = top;
}
void dfs(int x)
{
    for (int i = st[x]; i != -1; i = edge[i].nt)
    {
        dfs(edge[i].to);
        zhi[x] += zhi[edge[i].to];
    }
    if (zhi[x] != 1) ans = max(ans, zhi[x] * dian[x].len);
}
int main()
{
    memset(st, -1, sizeof(st));
    scanf("%s", s); cd = strlen(s);
    //printf("**\n");
    for (int i = 0; i < cd; i++) insert(s[i] - a+1);
    //printf("**\n");
    for (int i = 2; i <= cnt; i++)
        add(dian[i].fa, i);
    //printf("**\n");
    dfs(1);
    printf("%lld\n", ans);

    return 0;
}

 

算法学习:后缀自动机

标签:字母   不同的   解决问题   space   algo   top   queue   mem   pre   

原文地址:https://www.cnblogs.com/rentu/p/11508652.html

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