【模板】广义后缀自动机模板

建立在tire上的后缀自动机,采用bfs的建图方式,可以保证复杂度

#include<bits/stdc++.h>
using namespace std;
#define fu(a,b,c) for(int a=b;a<=c;++a)
#define fd(a,b,c) for(int a=b;a>=c;--a)
#define MAXN 2000010
#define LL long long
const int CHARSET_SIZE=10;
//Suffix_Automaton
struct Sam{
  Sam *ch[CHARSET_SIZE],*prt;
  int maxl;
  Sam(int maxl=0):maxl(maxl){}
};
struct Suffix_Automaton{
  Sam pool[MAXN<<1],*cur,*root;
  Suffix_Automaton(){
    cur=pool;
    root=new (cur++)Sam;
  }
  Sam *extend(int c,Sam *last){
    Sam *u=new (cur++)Sam(last->maxl+1),*v=last;
    for(;v&&!v->ch[c];v=v->prt)v->ch[c]=u;
    if(!v)u->prt=root;
    else if(v->ch[c]->maxl==v->maxl+1){
      u->prt=v->ch[c];
    }else{
      Sam *n=new (cur++)Sam(v->maxl+1),*o=v->ch[c];
      copy(o->ch,o->ch+CHARSET_SIZE,n->ch);
      n->prt=o->prt;
      o->prt=u->prt=n;
      for(;v&&v->ch[c]==o;v=v->prt)v->ch[c]=n;
    }
    return u;
  }
  LL solve(){
    LL ans=0;
    for(Sam *p=pool+1;p!=cur;p++)
      ans+=p->maxl-p->prt->maxl;
    return ans;
  }
}sam;
//Trie
struct Node{Node *ch[CHARSET_SIZE];};
struct Trie{
  Node pool[MAXN],*cur,*root;
  Trie(){cur=pool;}
  Node *insert(Node *last,int c){
    if(!last->ch[c])last->ch[c]=new (cur++)Node;
    return last->ch[c];
  }
  #define pi pair<Node*,Sam*>
  void bfs(){
    queue<pi> q;
    q.push(pi(root,sam.root));
    while(!q.empty()){
      pi u=q.front();q.pop();
      fu(i,0,9)
        if(u.first->ch[i]){
          Sam *tmp=sam.extend(i,u.second);
          q.push(pi(u.first->ch[i],tmp));
        }
    }
  }
}trie;
int main(){
  return 0;
}

原文地址:https://www.cnblogs.com/dream-maker-yk/p/9710625.html

时间: 2024-09-30 15:40:56

【模板】广义后缀自动机模板的相关文章

广义后缀自动机模板

后缀自动机能解决很多单串的问题.但是一旦到了多串的情况.可能就会变得有些棘手 这个时候你可能会想能不能将多个串一起构建出和单串后缀自动机那样子拥有诸多优美性质的自动机呢? 答案当然是有的.那就是广义后缀自动机 对于广义后缀自动机.和普通的后缀自动机写法上有些许不同之处 大致就是在插入新串的时候.需要把当前状态指针 last 指回 root 还有一个问题.网上的人们都说广义后缀自动机在新插入节点的时候要判是否已经存在 这个就造成了代码的迥异 关于代码.借鉴了这个博客 ==> Click here

hdu4622(后缀自动机模板)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4622 题意: 先输入一个长度为 n 的字符串, 然后有 q 个形如 l, r 的询问, 对于每个询问输出区间 [l, r] 中有多少不同的子串 思路: 后缀自动机模板 代码: 1 // 后缀自动机要理解其含义,从起点到每个点的不同路径,就是不同的子串. 2 // 到每一个点,不同路径,其实就是以这个点为最后一个字符的后缀,长度是介于(p->fa->len,p->len]之间的,个数也就清楚

【Luogu3804】【模板】后缀自动机(后缀自动机)

[Luogu3804][模板]后缀自动机(后缀自动机) 题面 洛谷 题解 一个串的出现次数等于\(right/endpos\)集合的大小 而这个集合的大小等于所有\(parent\)树上儿子的大小 这样子的话,给每个终止位置的\(size\)记为\(1\) 然后按照拓扑序累加,这就是\(right/endpos\)集合的大小 最后对于每个\(size>1\)的节点,\(ans=max(longest*size)\) #include<iostream> #include<cstdi

洛谷P3804 - 【模板】后缀自动机

Portal Description 模板题啦~ 推荐WJMZBMR在WC2012上的讲义<后缀自动机>. Code //[模板]后缀自动机 #include <cstdio> int max(int x,int y) {return x>y?x:y;} int const N=2e6+10; int n; char s[N]; int rt,ndCnt,last; int fa[N],ch[N][26],len[N],siz[N]; void ins(int x) { in

【BZOJ3926】[Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机

[BZOJ3926][Zjoi2015]诸神眷顾的幻想乡 Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴啦. 这时幽香发现了一件非常有趣的事情,太阳花田有n块空地.在过去,幽香为了方便,在这n块空地之间修建了n-1条边将它们连通起来.也就是说,这n块空地形成了一个树的结构. 有n个粉丝们来到了太阳花田上.为了表达对幽香生日的祝

E. Three strings 广义后缀自动机

http://codeforces.com/problemset/problem/452/E 多个主串的模型. 建立一个广义后缀自动机,可以dp出每个状态的endpos集合大小.同时也维护一个R[]表示那个串出现过. 所以可以算出每个状态的dp[i][k]表示第k个串在第i个状态中出现的次数. 可以知道sigma dp[i][0...k]是等于  endpos集合的大小. 然后把这个贡献加到min(i)....max(i)中去就可以了 差分一下. #include <bits/stdc++.h>

BZOJ 3277 串 (广义后缀自动机)

3277: 串 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 309 Solved: 118 [Submit][Status][Discuss] Description 字符串是oi界常考的问题.现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串(注意包括本身). Input 第一行两个整数n,k. 接下来n行每行一个字符串. Output 输出一行n个整数,第i个整数表示第i个字符串的答案. Sa

广义后缀自动机

1).自动机的介绍 首先我们先来介绍一下什么是自动机,有限状态自动机的功能是识别字符串,令一个自动机A,若他能识别字符串S,就记为A(S)=Ture,否则A(S)=False. 自动机由五个部分组成,alpha:字符集,state:状态集合,init:初始状态,end:结束状态集合,trans:状态转移函数. 令trans(s,ch)表示当前状态是s,在读入字符ch之后,所到达的状态.如果trans(s,ch)这个转移不存在,为了方便,设其为null,同时null只能转移到null.null表示

hdu 5853 Jong Hyok and String(广义后缀自动机)

题目链接:hdu 5853 Jong Hyok and String 题意: 给你n个字符串,m个询问,每次询问一个字符串 定义set(s)={(i,j)} 表示 s在第i个字符串中出现,且末尾位置为j. 对于一个询问,求set(Qi)=set(t) ,t串的数量. 题解: 如果是n=1,那么就是后缀自动机的一道裸题,答案就是Qi串匹配的最后一个节点x,ml[x]-ml[f[x]]. 现在是多个串,那么就建立一个广义后缀自动机.每次插入一个串后,将last=root,然后继续插下一个就行了. 最