Hdu 5384 Danganronpa (AC自动机模板)

题目链接:

  Hdu 5384 Danganronpa

题目描述:

  给出n个目标串Ai,m个模式串Bj,问每个目标串中m个模式串出现的次数总和为多少?

解题思路:

  Hdu 2222  Keywords Search十分相似,hdu2222求目标串中包含几个模式串,本题目求模式串在目标串中出现了几次(比赛的时候模板都不会就悲剧了┭┮﹏┭┮)

  初学AC自动机可以参考大神博客,总结的真的炒鸡棒讷。涨姿势请点击下面尊贵的链接大人:

  AC自动机算法总结            AC自动机模板

  学完AC自动机就可以套模板解决这个站在冰柜上的高冷题目了~~~~.

  对所有的Bj建立Trie图,然后在Trie的基础上建立fail数组,在fail数组上每遇到一个Bj的终点,都会对计算结果有1的贡献。

  1 #include <queue>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <algorithm>
  6 using namespace std;
  7 
  8 const int maxn = 100005;
  9 const int maxm = 10005;
 10 char A[maxn][maxm], B[maxm];
 11 
 12 struct Trie
 13 {
 14     int next[maxn][26], fail[maxn], end[maxn];
 15     int L, root;
 16 
 17     int newnode ()
 18     {
 19         for (int i=0; i<26; i++)
 20             next[L][i] = -1;
 21         end[L] = 0;
 22         return L++;
 23     }
 24 
 25     void init ()
 26     {
 27         L = 0;
 28         root = newnode();
 29     }
 30 
 31     void insert (char s[])
 32     {
 33         int now = root;
 34         for (int i=0; s[i]; i++)
 35         {
 36             if (next[now][s[i]-'a'] == -1)
 37                 next[now][s[i]-'a'] = newnode();
 38             now = next[now][s[i]-'a'];
 39         }
 40         end[now] ++;
 41     }
 42 
 43     void build ()
 44     {
 45         queue <int> Q;
 46         fail[root] = root;
 47         for (int i=0; i<26; i++)
 48             if (next[root][i] == -1)
 49             next[root][i] = root;
 50         else
 51         {
 52             fail[next[root][i]] = root;
 53             Q.push(next[root][i]);
 54         }
 55         while (!Q.empty())
 56         {
 57             int now = Q.front();
 58             Q.pop ();
 59             for (int i=0; i<26; i++)
 60             {
 61                 if (next[now][i] == -1)
 62                     next[now][i] = next[fail[now]][i];
 63                 else
 64                 {
 65                     fail[next[now][i]] = next[fail[now]][i];
 66                     Q.push (next[now][i]);
 67                 }
 68             }
 69         }
 70     }
 71 
 72     int query (char s[])
 73     {
 74         int now = root, res = 0;
 75         for (int i=0; s[i]; i++)
 76         {
 77             now = next[now][s[i] - 'a'];
 78             int temp = now;
 79             while (temp != root)
 80             {
 81                 res += end[temp];
 82                 temp = fail[temp];
 83             }
 84         }
 85         return res;
 86     }
 87 }ac;
 88 
 89 int main ()
 90 {
 91     int t, n, m;
 92     scanf ("%d", &t);
 93 
 94     while (t --)
 95     {
 96         ac.init ();
 97         scanf ("%d %d", &n, &m);
 98         for (int i=0; i<n; i++)
 99             scanf ("%s", A[i]);
100 
101         for (int i=0; i<m; i++)
102         {
103             scanf ("%s", B);
104             ac.insert (B);
105         }
106 
107         ac.build ();
108         for (int i=0; i<n; i++)
109         {
110             int res = ac.query(A[i]);
111             printf ("%d\n", res);
112         }
113 
114     }
115 
116     return 0;
117 }

 

  

转载于:https://www.cnblogs.com/alihenaixiao/p/4730202.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值