【HDU】2222 Keywords Search

【算法】AC自动机

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

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

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

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

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

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

时间: 2024-10-18 09:45:52

【HDU】2222 Keywords Search的相关文章

【HDOJ】2222 Keywords Search

AC自动机基础题. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <queue> 6 using namespace std; 7 8 #define MAXL 1000005 9 #define TRIEN 26 10 11 char des[MAXL], src[55]; 12 13 typedef

【题解】HDU-2222 Keywords Search

题目链接:HDU-2222  或  Vjudge 简单说明: ac自动机的建立,其中插入过程借助了字典树,处理回溯数组(也有人称失败数组)过程是一个广搜运用了STL的队列(queue).ac自动机的过程还在写. 这是学习ac自动机的第一题,如果wa的话,那就要注意,字串结束标记是如何标记的了.它不能单单 记录,还要 计数.WA了好几次-- my codes: #include <algorithm> #include <iostream> #include <cstring&

HDU 2222 - Keywords Search

试个模板- - /* HDU 2222 - Keywords Search [ AC自动机 ] */ #include <bits/stdc++.h> using namespace std; const int N = 500005; const int SIZE = 26; struct Trie { int ch[N][SIZE]; int f[N], last[N], cnt[N], val[N]; int tot, ans; void init() { tot = 0; memset

HDU 2222——Keywords Search(AC自动机)

Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 34020    Accepted Submission(s): 11009 Problem Description In the modern time, Search engine came into the life of everybody like

HDU 2222 Keywords Search AC自动机入门题

单词统计的题目,给出一些单词,统计有多少单词在一个文本中出现,最经典的入门题了. AC自动机的基础: 1 Trie, 以这个数据结构为基础的,不过增加一个fail指针和构造fail的函数 2 KMP,不是直接运用KMP,而是需要KMP的思想,KMP思想都没有的话,理解这个算法会更加吃力的. 注意本题的单词会有重复出现的,一个单词只能统计一次. 搜索了一下网上的题解,发现好多代码都是一大抄的啊,⊙﹏⊙b汗. 本博客的乃是原创代码,代码风格也是差不多固定的,转载请注明出处:http://blog.c

【HDU】2147 kiki&#39;s game

http://acm.hdu.edu.cn/showproblem.php?pid=2147 题意:n×m的棋盘,每次可以向左走.向下走.向左下走,初始在(1, m),n,m<=2000,问先手是否胜利. #include <cstdio> using namespace std; int main() { int n, m; while(scanf("%d%d", &n, &m), n|m) (n&1)&&(m&1)?

【LeetCode】Validate Binary Search Tree

Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as follows: The left subtree of a node contains only nodes with keys less than the node's key. The right subtree of a node contains only nodes with keys

【HDU】4923 Room and Moor(2014多校第六场1003)

Room and Moor Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 263    Accepted Submission(s): 73 Problem Description PM Room defines a sequence A = {A1, A2,..., AN}, each of which is either 0

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

传送门:pid=4888">[HDU]4888 Redraw Beautiful Drawings 题目分析: 比赛的时候看出是个网络流,可是没有敲出来.各种反面样例推倒自己(究其原因是不愿意写暴力推断的).. 首先是简单的行列建边.源点向行建边.容量为该行元素和,汇点和列建边.容量为该列元素和.全部的行向全部的列建边,容量为K. 跑一次最大流.满流则有解,否则无解. 接下来是推断解是否唯一. 这个题解压根没看懂.还是暴力大法好. 最简单的思想就是枚举在一个矩形的四个端点.设A.D为主对角