后缀自动机 板子

后缀自动机

并没有搞的很清楚,凭着当前的理解胡乱bb两句得了,内容存在误导,请仔细甄别。

  • endpos集合

    每个子串结尾的位置集合。

  • 本质相同

    endpos相等的子串集合

    然后这个本质不同的集合构成自动机的状态。

  • \(substr(i)\),状态\(i\)包含的子串集合

    \(len(i)\),状态\(i\)包含的最长子串

    性质:状态\(i\)包含的子串是最长子串长度连续的一段后缀。

  • 后缀连接(\(parent\)边)

    状态\(i\)最小子串的后缀为什么不在里面呢?

    因为在别的地方出现了后缀,被分到别的状态了。

    那么当前状态对这个别的状态连边即是后缀连接。

  • 构造流程(在线增量法)
    1. 新建一个点,然后走上一个点的parent边,如果状态未对当前连边,连上。
    2. 1步骤在根结束,par边连虚根1
    3. 1步骤在\(p\)结束
      • 如果\(p\)的后面的点与\(p\)长度差一个,\(par\)指中国后面的点,这里没有产生新状态
      • 不止差一个,\(p\)的末尾状态掉了,再开一个状态存一下,然后把东西继承一下,然后旧状态抵回去,最后新点再更新一下信息。
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using std::max;
const int N=2e6+10;
int head[N],to[N],Next[N],cnt;
void add(int u,int v){to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;}
int tot=1,las=1,ch[N][26],siz[N],par[N],len[N],n;
ll ans;char s[N];
void extend(int c)
{
    int now=++tot,p=las;
    len[now]=len[las]+1,siz[now]=1;
    while(p&&!ch[p][c]) ch[p][c]=now,p=par[p];
    if(!p) par[now]=1;
    else
    {
        int x=ch[p][c];
        if(len[p]+1==len[x]) par[now]=x;
        else
        {
            int y=++tot;
            len[y]=len[p]+1,par[y]=par[x];
            memcpy(ch[y],ch[x],sizeof(ch[x]));
            while(p&&ch[p][c]==x) ch[p][c]=y,p=par[p];
            par[now]=par[x]=y;
        }
    }
    las=now;
}
void dfs(int now)
{
    for(int i=head[now];i;i=Next[i])
        dfs(to[i]),siz[now]+=siz[to[i]];
    if(siz[now]>1) ans=max(ans,1ll*siz[now]*len[now]);
}
int main()
{
    scanf("%s",s+1),n=strlen(s+1);
    for(int i=1;i<=n;i++) extend(s[i]-'a');
    for(int i=2;i<=tot;i++) add(par[i],i);
    dfs(1);
    printf("%lld\n",ans);
    return 0;
}


2019.1.4

原文地址:https://www.cnblogs.com/ppprseter/p/10222207.html

时间: 2024-10-23 04:35:42

后缀自动机 板子的相关文章

后缀自动机板子

后缀自动机 是什么? 博主不想写反正没人看 直接去\(hihocoder\) 1 2 模板 # include <bits/stdc++.h> # define IL inline # define RG register # define Fill(a, b) memset(a, b, sizeof(a)) using namespace std; typedef long long ll; template <class Int> IL void Input(RG Int &a

SPOJ - NSUBSTR 后缀自动机板子

SPOJ - NSUBSTR #include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PII pair<int, int> #define PLI pair<LL, int> #define PDD pair<double,double> #define ull unsigned long long

后缀自动机(SAM)

*在学习后缀自动机之前需要熟练掌握WA自动机.RE自动机与TLE自动机* 什么是后缀自动机 后缀自动机 Suffix Automaton (SAM) 是一个用 O(n) 的复杂度构造,能够接受一个字符串所有后缀的自动机. 它最早在陈立杰的 2012 年 noi 冬令营讲稿中提到. 在2013年的一场多校联合训练中,陈立杰出的 hdu 4622 可以用 SAM 轻松水过,由此 SAM 流行了起来. 一般来说,能用后缀自动机解决的问题都可以用后缀数组解决.但是后缀自动机也拥有自己的优点. 1812.

后缀自动机/后缀树

只是笔记罢了,不要看 关于DAWG: 见紫书P390 把后缀自动机上所有节点都设为接受态就形成DAWG,可以接受一个字符串的所有子串. 一个子串的end-set是它在原串w中出现位置(从1开始编号)的右端点集合. 在DAWG中,end-set相同的子串属于同一个状态. 原因没原因,这应该算定义吧? 任意两个节点的end-set要么不相交,要么是包含关系. 原因:在DAWG上走一步,当前end-set的变化是将原end-set中各个元素+1(要去掉超出字符串长度的元素),然后拆分成1个或多个新en

bzoj 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式【后缀自动机】

就是后缀自动机的板子嘛..构造完自动机之后拓扑一下,记录size,对于size大于k的点和ans取max #include<iostream> #include<cstdio> #include<cstring> #include<map> using namespace std; const int N=100005; int n,m,a[N],cur=1,cnt=1; int read() { int r=0,f=1; char p=getchar();

关于后缀自动机的一些理解

咕咕咕了好久的东西,以前只是粗糙的背个板子之类的,并未对parent树有什么深刻的理解 clj姐姐tql,这么神仙的东西是怎么想出来的啊 个人认为有以下几点是难以理解的: 一.right集合的定义: right集合就是指某一子串在原串当中出现的所有的位置的集合,也在某位大佬博客中叫做endpos集合: 二.right集合(endpos集合)相同的我们称为endpos等价类(重点理解) 三.对于任意两个endpos集合中,那么必然为其中一个为另一个的子串,或者两者绝无交集 四.endpos的等价类

后缀自动机做题记录

目录 后缀自动机做题记录 sp1811 sp1812 sp10570 luogu 2463 CF873F TJOI2015 弦论 AHOI2013 差异 HEOI2016/TJOI2016 字符串 HAOI2016 找相同字符 SDOI2016 生成魔咒 ZJOI2015 诸神眷顾的幻想乡 留坑待填 广义SAM 其他 NOI原题练习 后缀自动机做题记录 来填之前的坑了...考后大概会做做有字符串的综合题吧 sp1811 lcs板子,对于第一个串建出SAM,第二个串在上面跑,即可求出对于每一个位置

「后缀自动机」

前言 这比后缀数组难啊. 但似乎其实我并不觉得比sa好用. 很难懂,本来看了一天的证明现在屁都没剩,事实证明打板子才是对的. 应用 很多,但我都不会. 求第K大 本质不同的子串 求排名 多个串求最长公共串 所以我为什么要写总结啊喂. #include<bits/stdc++.h> using namespace std; const int N=5000; int n,lst,cnt,len[N],buc[N],ch[N][26],fa[N],mx[N],mn[N],rk[N]; char s

hiho一下第128周 后缀自动机二&#183;重复旋律5

#1445 : 后缀自动机二·重复旋律5 时间限制:10000ms 单点时限:2000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数列. 现在小Hi想知道一部作品中出现了多少不同的旋律? 解题方法提示 输入 共一行,包含一个由小写字母构成的字符串.字符串长度不超过 1000000. 输出 一行一个整数,表示答案. 样例输入 aab 样例输出 5 解题方法提示 小Hi:本周的题目其实就是给定一个字符串S,要求出S的所有不同子串的数