HDU5384——AC自动机——Danganronpa

http://acm.hdu.edu.cn/showproblem.php?pid=5384

/*
AC自动机是用来求多字符串匹配问题,所需要掌握的基础是KMP和trie
对匹配子串建立一棵trie树,对这棵树进行KMP匹配
*/
/************************************************
* Author        :Powatr
* Created Time  :2015-8-14 20:23:01
* File Name     :HDU2222.cpp
 ************************************************/

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int MAXN = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;

string s1[MAXN], s2[MAXN];
struct AC{
    int trie[MAXN][26], num[MAXN], fail[MAXN];
    ll val[MAXN];
     int pos;
    void inti()
    {
        memset(trie, 0, sizeof(trie));
        memset(val, 0, sizeof(val));
        pos = 1;
    }
    void insert(string s)
    {
        int c = 0;
        int len = s.size();
        for(int i = 0; i < len; i++){
            int m = s[i] - 'a';
            if(!trie[c][m]){
                memset(trie[pos], 0, sizeof(trie[pos]));
                val[pos] = 0;
                trie[c][m] = pos++;
            }
            c = trie[c][m];
        }
        val[c]++;
    }
    void get_fail()
    {
        queue<int> q;
        fail[0] = 0;
        for(int i = 0; i < 26; i++){
            if(trie[0][i]){
                fail[trie[0][i]] = 0;
                q.push(trie[0][i]);
            }
        }
        while(!q.empty()){
            int r = q.front();
            q.pop();
            for(int i = 0; i < 26; i++){
             int   u = trie[r][i];
                if(!u){
                    trie[r][i] = trie[fail[r]][i];
                    continue;
                }
                q.push(u);
                fail[u] = trie[fail[r]][i];
                val[u] += val[fail[u]];
            }
        }
    }
    long long  find(string s)
    {
        ll ans = 0;
        int len = s.size();
        int j = 0;
        for(int i = 0; i < len; i++){
            int m = s[i] - 'a';
            j = trie[j][m];
            ans += val[j];
        }
        return ans;
    }
}ac;

int main()
{
    int T;
    scanf("%d", &T);
    int n, m;
    while(T--){
        scanf("%d%d", &n, &m);
        for(int i = 0; i < n; i++) cin >> s1[i];
        for(int i = 0; i < m; i++) cin >> s2[i];
        ac.inti();
        for(int i = 0 ; i < m; i++) ac.insert(s2[i]);
        ac.get_fail();
        for(int i = 0 ; i < n; i++){
            printf("%I64d\n", ac.find(s1[i]));
        }
    }
    return 0;
}

  

转载于:https://www.cnblogs.com/zero-begin/p/4731235.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值