【算法】AC自动机

【题解】本题注意题意是多少关键字能匹配而不是能匹配多少次,以及可能有重复单词。

询问时AC自动机与KMP最大的区别是因为建立了trie,所以对于目标串T与自动机串是否匹配只需要直接访问对应结点,而不用真的比较。

因此可以预处理出拥有对应节点的失配串,不用一次一次跑前跑去找一样的。

然后还有就是一个结点可能对应多个串,所以需要last使统计答案完整。

AC自动机的细节标注在代码里了。

AC自动机过程:

[trie]

for 长度

if(!ch[u][c])初始化,ch[u][c]=++sz;

else u=ch[u][c];

val[u]=...;

[getfail]

初始进队

队:u

  for 26(处理u点后续节点)

    if(!u)ch[x][c]=ch[p[x][c],continue;(没有该点,则考虑直接走失配直到有此点的串,由于层层前推实际上前一个即可)

    u进队;(有此点)

    int j=p[x];

    while(j>0&&!ch[j][c])j=p[j];(走失配直到有此点的串

    p[u]=ch[j][c];(记录失配边)

    last[u]=val[p[u]]?p[u]:last[p[u]];(记录同结尾价值点)

[find]

[askans]

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxnode=,maxn=,maxlen=;
int val[maxnode],sz,ch[maxnode][],p[maxnode],last[maxnode],q[];
long long ans;
char s[maxlen];
int idx(char c){return c-'a'+;}
void trie(char s[])
{
int u=,m=strlen(s+);
for(int i=;i<=m;i++)
{
int c=idx(s[i]);
if(!ch[u][c])
{
sz++;
memset(ch[sz],,sizeof(ch[sz]));//初始化
val[sz]=;//初始化
ch[u][c]=sz;
}
u=ch[u][c];
}
val[u]++;
}
void getfail()
{
int head=,tail=;//初始队列不能有队头!
p[]=;last[]=;//trie根初始化
for(int c=;c<=;c++)
{
int u=ch[][c];
if(u){p[u]=;last[u]=;q[tail++]=u;}
}
while(head!=tail)
{
int x=q[head++];if(head>)head=;
for(int c=;c<=;c++)
{
int u=ch[x][c];
if(!u){ch[x][c]=ch[p[x]][c];continue;}//直接得到可匹配字符串,无则为0。
q[tail++]=u;if(tail>)tail=;
int j=p[x];
while(j>&&!ch[j][c])j=p[j];
p[u]=ch[j][c];
last[u]=val[p[u]]?p[u]:last[p[u]];
}
}
}
void askans(int j)
{
while(j)
{
ans+=val[j];
val[j]=;
j=last[j];
}
}
void find(char s[])
{
int m=strlen(s+);
int j=;
for(int i=;i<=m;i++)
{
int c=idx(s[i]);
j=ch[j][c];//直接得到
if(val[j])askans(j);
else if(last[j])askans(last[j]);
}
}
int main()
{
int tt;
scanf("%d",&tt);
while(tt--)
{
int n;
scanf("%d",&n);
sz=;//根节点标号为0
memset(ch[],,sizeof(ch[]));//初始化根节点即可,建树中需要会继续清理,保持有效与无效结点中间始终存在断层。
for(int i=;i<=n;i++)
{
scanf("%s",s+);
trie(s);//传过去的一定要是s,不能是s+1
}
getfail();
scanf("%s",s+);
ans=;
find(s);
printf("%lld\n",ans);
}
return ;
}

AC自动机

【HDU】2222 Keywords Search的更多相关文章

  1. 【HDU】2222 Keywords Search(AC自动机)

    题目 传送门:QWQ 分析 $ AC $自动机模板,黈力的码风真的棒极了,这是我抄他的. 还有 题号不错 代码 #include <cstdio> #include <cstring ...

  2. 【HDOJ】2222 Keywords Search

    AC自动机基础题. #include <iostream> #include <cstdio> #include <cstring> #include <cs ...

  3. HDU 2222 Keywords Search(查询关键字)

    HDU 2222 Keywords Search(查询关键字) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K ...

  4. 【HDU】4888 Redraw Beautiful Drawings 网络流【推断解是否唯一】

    传送门:pid=4888">[HDU]4888 Redraw Beautiful Drawings 题目分析: 比赛的时候看出是个网络流,可是没有敲出来.各种反面样例推倒自己(究其原因 ...

  5. AC自动机 HDOJ 2222 Keywords Search

    题目链接 题意:每个文本串的出现次数 分析:入门题,注意重复的关键字算不同的关键字,还有之前加过的清零.   新模板,加上last跑快一倍 #include <bits/stdc++.h> ...

  6. 【刷题】HDU 2222 Keywords Search

    Problem Description In the modern time, Search engine came into the life of everybody like Google, B ...

  7. hdoj 2222 Keywords Search 【AC自己主动机 入门题】 【求目标串中出现了几个模式串】

    Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others ...

  8. HDU 2222 Keywords Search(AC自动机模版题)

    Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others ...

  9. HDU 2222 Keywords Search(瞎搞)

    Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others ...

随机推荐

  1. sql分页使用join提高性能

    今天在分析系统中的分页sql时意外知道了使用join可以提高分页性能. 逻辑是join部分使用单一表,单一字段排序分页,然后join大表.

  2. Matlab 中的varargin/nargin varargout/nargout

    Varargin = var+ arg+ in = variable length(可变长) input argument(输入参数) list(列表) :允许调用该函数时根据需要改变输入参数的个数 ...

  3. 从Mysql某一表中随机读取n条数据的SQL查询语句

    若要在i ≤ R ≤ j 这个范围得到一个随机整数R ,需要用到表达式 FLOOR(i + RAND() * (j – i + 1)).例如, 若要在7 到 12 的范围(包括7和12)内得到一个随机 ...

  4. delphi 取得数据集某字段值的六种方法

    //取name字段的示例   edit1.Text:=ADOquery1.Fields[2].AsString;   //取得数据表的第二个字段的值 edit2.Text:=ADOquery1.Fie ...

  5. fzu1686-神龙的难题

    给出一个n\times m的01矩阵,以及\(h,w\),表示一次可以把矩阵的一个\(h\times w\)的小矩阵变为全0,问至少要多少次可以把整个矩阵变为全0.\(n,m\le 15\). 分析 ...

  6. CentOS7 从查看、启动、停止服务说起systemctl

    执行命令“systemctl status 服务名.service”可查看服务的运行状态,其中服务名后的.service 可以省略,这是CenOS7以后采用systemd作为初始化进程后产生的变化. ...

  7. 【以前的空间】vijos 1720 阿狸的打字机

    https://www.vijos.org/p/1720 作为一个一个蒟蒻,跪了三个星期,终于在蔡大神的帮助下a了.这题网上的题解很多,不过大都把题解写的太简单了(对因为大神的题解只有三个字:傻叉题) ...

  8. BZOJ3571 & 洛谷3236:[HNOI2014]画框——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=3571 https://www.luogu.org/problemnew/show/P3236 小T ...

  9. BZOJ5292 & 洛谷4457 & LOJ2513:[BJOI2018]治疗之雨——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=5292 https://www.luogu.org/problemnew/show/P4457 ht ...

  10. BZOJ2111:[ZJOI2010]排列计数——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=2111 https://www.luogu.org/problemnew/show/P2606#su ...