传送门:QAQQAQ

定义nxt[u]=v表示从u开始不断沿着失配边跳到的第一个是标记点的端点v,那么我们再匹配时沿着last跳,每跳到一个last,它就一定对应一个模式串,所以效率是非常高的。

和KMP一样,我们只需检测ch[u][c]和ch[nxt[u]][c]的下一个字符是否相同,即可进行nxt数组的初始化,即:

从0~25枚举c,令v=ch[u][c]

则nxt[v]=ch[nxt[u]][c]。

这个nxt[v]并不能保证ch[u][c]就一定存在,所以还需要一个while循环一直跳直到找到一个ch[u][c]!=0的端点。出现了一个while,既使代码不够优美,又使效率无法保证.

所以我们直接把所有ch[k][c]=0的端点的ch[k][c]直接连向ch[nxt[k]][c],就好像并差集的一个路径压缩,由于Trie是读完所有模式串后建的,所以这个加边并不会影响Trie,这样就不用担心节点是否存在的问题了(无论如何都会在根节点1上停止,我们先创建一个虚拟节点0,把0的26条边都连在1上,令nxt[1]=0,那么后面无论情况再糟最后也只是nxt[x]=1)。

考虑到这是一个Trie树上的递推,所以我们用BFS搞一搞就好了。

在查询时,只需对于当前字符串不停跳nxt,判断是否是模式串的结尾即可,因为ch[k][c]=0的端点的ch[k][c]直接连向ch[nxt[k]][c],所以不用担心从前往后枚举文本串的前缀会过长。

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=(int)(2e9);
const ll INF=(ll)(5e18);
const int N=; //nxt:保存最长的后缀字串
char s[N];
int nxt[N],n,ch[N][],cnt=;
int bl[N],ans=; void make(char *s)
{
int len=strlen(s),u=;
for(int i=;i<len;i++)
{
int c=s[i]-'a';
if(!ch[u][c]) ch[u][c]=++cnt;
u=ch[u][c];
}
bl[u]++;//不能只赋值为1,可能有完全相同的字符串
} void bfs()
{
for(int i=;i<;i++) ch[][i]=;
queue<int> q;
q.push(); nxt[]=;
while(!q.empty())
{
int u=q.front(); q.pop();
for(int i=;i<;i++)
{
if(!ch[u][i]) ch[u][i]=ch[nxt[u]][i];//剪枝
else
{
int v=ch[u][i];
nxt[v]=ch[nxt[u]][i];
q.push(v);
}
}
}
} void query(char *s)
{
int len=strlen(s),u=;
for(int i=;i<len;i++)
{
int c=s[i]-'a';
int k=ch[u][c];
while(k>&&bl[k]!=-)
{
ans+=bl[k];
bl[k]=-;//剪枝
k=nxt[k];
}
u=ch[u][c];
}
printf("%d\n",ans);
} int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%s",s);
make(s);
}
bfs();
scanf("%s",&s);
query(s);
return ;
}

模板——AC自动机的更多相关文章

  1. luoguP3808[模板]AC自动机(简单版)

    传送门 ac自动机模板题,裸的多串匹配 代码: #include<cstdio> #include<iostream> #include<algorithm> #i ...

  2. luoguP3796[模板]AC自动机(加强版)

    传送门 ac自动机模板,可能我写的ac自动机是有点问题的,所以跑的有些慢 暴力跳fail统计 代码: #include<cstdio> #include<iostream> # ...

  3. 算法模板——AC自动机

    实现功能——输入N,M,提供一个共计N个单词的词典,然后在最后输入的M个字符串中进行多串匹配(关于AC自动机算法,此处不再赘述,详见:Aho-Corasick 多模式匹配算法.AC自动机详解.考虑到有 ...

  4. 模板 AC自动机

    题目描述 有$N$ 个由小写字母组成的模式串以及一个文本串$T$ .每个模式串可能会在文本串中出现多次.你需要找出哪些模式串在文本串$T$ 中出现的次数最多. 输入输出格式 输入格式: 输入含多组数据 ...

  5. 算法竞赛模板 AC自动机

    AC自动机基本操作 (1) 在AC自动机中,我们首先将每一个模式串插入到Trie树中去,建立一棵Trie树,然后构建fail指针. (2) fail指针,是穿插在Trie树中各个结点之间的指针,顾名思 ...

  6. 洛谷.3808/3796.[模板]AC自动机

    题目链接:简单版,增强版 简单版: #include <cstdio> #include <cstring> const int N=1e6+5,S=26; char s[N] ...

  7. 模板—AC自动机

    #include<iostream> #include<cstdio> #include<cstring> using namespace std; struct ...

  8. AC自动机例题

    P3808 [模板]AC自动机(简单版) [题目描述] 给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过. #include<bits/stdc++.h> using name ...

  9. 「kuangbin带你飞」专题十七 AC自动机

    layout: post title: 「kuangbin带你飞」专题十七 AC自动机 author: "luowentaoaa" catalog: true tags: - ku ...

随机推荐

  1. uoj#209【UER #6】票数统计

    题目 做UER的A题涨信心 首先我们注意到这个所谓的至少有一条正确在\(x\)和\(y\)不相等的时候非常弱,当\(x<y\)时,只有可能是后\(y\)位用户有\(x\)个通过:当\(x> ...

  2. 【POJ】3268 Silver Cow Party

    题目链接:http://poj.org/problem?id=3268 题意 :有N头奶牛,M条单向路.X奶牛开party,其他奶牛要去它那里.每头奶牛去完X那里还要返回.去回都是走的最短路.现在问这 ...

  3. sql 递归查询,刁刁的

    with cte as( select IDPlus,SuperiorsIDPlus,RoleGrade,viplevel,NAME,WeixinId from Member where IDPlus ...

  4. Java常用文件下载与查找的URL

    Java JDK: http://www.oracle.com/technetwork/java/javase/downloads/index.html Tomcat: http://tomcat.a ...

  5. IOS配置cocos2d-x

    cd /Users/wyc/Desktop/cocos2d-x-3.16/tools/cocos2d-console/bin python cocos.py new HelloWorldDemo -p ...

  6. 8_InlineHook

    1 shellcode低2Gb警告.应使用高2GB 稳定 : 在内核挂钩子: 由于每个进程的低2gb 的数据是不同的:所以 在内核挂钩子 因该把 代码 放在 高 2gb. 方法1(申请): 比如 使用 ...

  7. UEditor 编辑模板

    读取模板,放到ueditor中进行编辑 @model WeiXin_Shop.Models.WX_GoodsDetails @Html.Partial("_MasterPage") ...

  8. Qt Creator编译时提示找不到“ui_xxx.h”文件

    解决方案: 在对应工程的*.pro文件里加上: QT+= widgets 则在编译过程中对应的“xxx.ui”文件会自动生成“ui_xxx.h”文件.

  9. 20170702-变量说明,静态方法,类方法区别,断点调试,fork,yield协程,进程,动态添加属性等。。

    概念: 并行:同时运行 并发:看似同时运行  json后任然中文的问题 import json d = {"名字":"初恋这件小事"} new_d1 = jso ...

  10. 计算几何——直线交点poj1269

    求直线交点还是要推一个公式的.. 见博客https://blog.csdn.net/u013050857/article/details/40923789 还要学一下向量的定点比分法 另外poj精度好 ...