KMP

void kmp(char t[],char p[])
{
int n=strlen(t),m=strlen(p);
int *f=new int[m];
f[0]=f[1]=0;
for(int i=1;i<m;++i)
{
int j=f[i];
while(j&&p[i]!=p[j])j=f[j];
f[i+1]=p[j]==p[i]?j+1:0;
}
for(int i=0,j=0;i<n;++i)
{
while(j&&t[i]!=p[j])j=f[j];
if(t[i]==p[j])j++;
if(j==m)printf("%d\n",i-m+1);
}
delete[] f;
}

Aho-Corasick automa

Trie + fail[] & last[] + matching

int fail[int i]失配函数,注意i和fail[i]结点对应的字母相同;f[0]=0,f[ch[0][u]]=0。

int last[int i]沿失配函数往回走遇到的第一个单词结点。(可选)

输出所有与前i位的后缀匹配的单词的val值

可能有错

const int maxn=1e6+5;
struct trie
{
int ch[500010][26],val[maxn],fail[maxn],last[maxn];
int sz;
trie(){sz=0;ms(ch[0],0);}
void Insert(char s[],int v)
{
int u;for(u=0;*s;++s){if(!ch[u][*s-'a']){ch[u][*s-'a']=++sz;ms(ch[sz],0);}u=ch[u][*s-'a'];val[u]=0;}
val[u]=v;
}
void GetFailLast()
{
queue<int> q;while(!q.empty())q.pop();q.push(0);fail[0]=0;for(int i=0;i<26;++i)fail[ch[0][i]]=0;
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=0;i<26;++i)
{
int v=ch[u][i],t=fail[u];;if(!v)continue;
q.push(v);
while(t&&!ch[t][i])t=fail[t];
fail[v]=ch[t][i];last[v]=val[fail[v]]?fail[u]:last[fail[v]];
}
}
}
void Query(char s[])
{
for(int u=0,i=0;*s;s++,i++){while(u&&!ch[u][*s-'a'])u=fail[u];u=ch[u][*s-'a'];int tmp=val[u]?u:last[u];while(tmp)printf("%d %d\n",i,val[tmp]),tmp=last[tmp];}
}
}T;

另一版本

  • ch[][]给出了自动机状态转移图的完整邻接表
  • 加上根结点一共sz个结点,其中根结点标号为0,其余分别为1,...,sz-1
  • 查询时,每一步都需要沿fail[]往回检查
  • -1表示结点不存在(用memset初始化是可行的。memset可以初始化0和-1)
const int sigma_size=26,max_node=100;
struct Trie
{
int ch[max_node][sigma_size],val[max_node],fail[max_node],sz;
int newnode(){memset(ch[sz],-1,sizeof ch[sz]);val[sz]=0;return sz++;}
void init(){sz=0;newnode();}
void insert(char s[],int v)
{
int u;for(u=0;*s;++s){if(ch[u][*s-'a']==-1)ch[u][*s-'a']=newnode();u=ch[u][*s-'a'];}
val[u]=v;
}
void build()
{
queue<int>q;
for(int i=0;i<sigma_size;++i)
{
int &v=ch[0][i];
if(v==-1)v=0;
else {fail[v]=0;q.push(v);}
}
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=0;i<sigma_size;++i)
{
int &v=ch[u][i];
if(v==-1)v=ch[fail[u]][i];
else{fail[v]=ch[fail[u]][i];q.push(v);}
}
}
}
void query(char s[])
{
for(int u=0,t,cnt=0;*s;++s,++cnt)
{
t=u=ch[u][*s-'a'];
while(t){if(val[t])printf("%d %d\n",cnt,val[t]);t=fail[t];}
}
}
}T;

KMP & AC自动机的更多相关文章

  1. 字符串的模板 Manacher kmp ac自动机 后缀数组 后缀自动机

    为何scanf("%s", str)不需要&运算 经常忘掉的字符串知识点,最好不加&,不加&最标准,指针如果像scanf里一样加&是错的,大概是未定 ...

  2. Trie树&kmp&AC自动机&后缀数组&Manacher

    Trie 计数+Trie,读清题意很重要 https://vjudge.net/problem/UVALive-5913 kmp AC自动机 模板:https://vjudge.net/problem ...

  3. 2021.11.09 P4824 [USACO15FEB]Censoring S与P3121 [USACO15FEB]Censoring G(KMP&&AC自动机)

    2021.11.09 P4824 [USACO15FEB]Censoring S与P3121 [USACO15FEB]Censoring G(KMP&&AC自动机) https://w ...

  4. 关于Trie KMP AC自动机

    个人认为trie,KMP,AC自动机是思想非常明确的,AC自动机的性质是与KMP算法的思想类似的(失配后跳转) 而KMP是线性的,AC自动机是在tire树上跑KMP,为方便那些不会用指针的小朋友(我也 ...

  5. hdu1686 Oulipo KMP/AC自动机

    The French author Georges Perec (1936–1982) once wrote a book, La disparition, without the letter 'e ...

  6. 「模拟赛20180306」回忆树 memory LCA+KMP+AC自动机+树状数组

    题目描述 回忆树是一棵树,树边上有小写字母. 一次回忆是这样的:你想起过往,触及心底--唔,不对,我们要说题目. 这题中我们认为回忆是这样的:给定 \(2\) 个点 \(u,v\) (\(u\) 可能 ...

  7. 优先队列 + 并查集 + 字典树 + 欧拉回路 + 树状数组 + 线段树 + 线段树点更新 + KMP +AC自动机 + 扫描线

    这里给出基本思想和实现代码 . 优先队列 : 曾经做过的一道例题       坦克大战 struct node { int x,y,step; friend bool operator <(no ...

  8. AC自动机【萌新文章】

    我这个蒟蒻第一次写博客,有点小激动呢. 主要是最近刚学了AC自动机,学得糟糟糕糕,记录一下,看到dalao们都在写博客,决定自己也写一波[我好水的啦,写的也不好] AC自动机大概就是    Trie+ ...

  9. 【BZOJ3940】【BZOJ3942】[Usaco2015 Feb]Censoring AC自动机/KMP/hash+栈

    [BZOJ3942][Usaco2015 Feb]Censoring Description Farmer John has purchased a subscription to Good Hoov ...

随机推荐

  1. 1~n的之间的k个数组成和为n的方案数(动态规划)

    绯色的子弹 Description 众所周知,夏季奥林匹克运动会时隔56年第二次在东京举办,紧接着出来的<名侦探柯南 M24绯色的子弹>竟也是有奥运会的背景,最重要的是重归主线!!!(赤井 ...

  2. Pointer Lock API(2/3):属性、方法、事件

    Pointer Lock API 提供了三个属性.两个方法.两个事件 Tabel Of Content 属性 Document.pointerLockElement Document.onpointe ...

  3. JS中this指向问题和改变this指向

    首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然 ...

  4. spark模型error java.lang.IllegalArgumentException: Row length is 0

    failure: Lost task 18.3 in stage 17.0 (TID 59784,XXXXX, executor 19): java.lang.IllegalArgumentExcep ...

  5. mount --bind绑定命令

    将目录或文件DirFile-1绑定到目录或文件DirFile-2上,所有对DirFile-2的访问就是对DirFile-1的访问 mount --bind [DirFile-1] [DirFile-2 ...

  6. tf.nn.conv2d 卷积

    tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, name=None) 第一个参数input:指需要做卷积的输入 ...

  7. web.xml配置参数context-param和init-param的区别

    web.xml配置参数context-param和init-param的区别 (2009-04-13 10:29:01) 转载▼ 标签: 杂谈 分类: JavaEE web.xml里面可以定义两种参数 ...

  8. Java创建线程的三种形式的区别以及优缺点

    1.实现Runnable,Callable Callable接口里定义的方法有返回值,可以声明抛出异常. 继承Callable接口实现线程 class ThreadCall implements Ca ...

  9. python 3 的解释器

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:Yangtze PS:如有需要Python学习资料的小伙伴可以加点击下 ...

  10. E. Max Gcd

    单点时限: 2.0 sec 内存限制: 512 MB 一个数组a,现在你需要删除某一项使得它们的gcd最大,求出这个最大值. 输入格式 第一行输入一个正整数n,表示数组的大小,接下来一行n个数,第i个 ...