SP8093 JZPGYZ - Sevenk Love Oimaster(SAM)

本文介绍了一道AC自动机模板题的解决方法,通过构建AC自动机来处理字符串匹配问题,实现对多个字符串的高效查找。文章详细展示了AC自动机的构建过程及如何更新节点的匹配计数。
/*
打模板题啊
每个串影响到的集合直接枚举跳parent处理即可 

*/
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<iostream>
#define ll long long 
#define M 400010
#define mmp make_pair
using namespace std;
int read()
{
    int x;
    cin >> x;
    return x;
}
int ch[M][26], fa[M], len[M], cnt = 1, lst, n, m;
string a[M], b; 

void insert(int c)
{
    int p = ++cnt, f = lst;
    lst = p;
    len[p] = len[f] + 1;
    while(f && !ch[f][c]) ch[f][c] = p, f = fa[f];
    if(!f)
    {
        fa[p] = 1;
    }
    else
    {
        int q = ch[f][c];
        if(len[q] == len[f] + 1)
        {
            fa[p] = q;
        }
        else
        {
            int nq = ++cnt;
            fa[nq] = fa[q];
            memcpy(ch[nq], ch[q], sizeof(ch[q]));
            len[nq] = len[f] + 1;
            fa[q] = fa[p] = nq;
            while(f && ch[f][c] == q) ch[f][c] = nq, f = fa[f];
        }
    }
}
int cor[M], ans[M];
int main()
{
    ios::sync_with_stdio(false);    
    n = read(), m = read();
    for(int i = 1; i <= n; i++)
    {
        cin >> a[i];
        lst = 1;
        for(int j = 0; j < a[i].size(); j++) insert(a[i][j] - 'a');
    }
    for(int i = 1; i <= n; i++)
    {
        int now = 1;
        for(int j = 0; j < a[i].size(); j++)
        {
            now = ch[now][a[i][j] - 'a'];
            int tmp = now;
            while(tmp && cor[tmp] != i) cor[tmp] = i, ans[tmp]++, tmp = fa[tmp]; 
        }
    }
    while(m--)
    {
        cin >> b;
        int now = 1, as = 0;
        for(int i = 0; i < b.size(); i++)
        {
            now = ch[now][b[i] - 'a'];
            if(!now) break;
        }
        as = ans[now];
        cout << as << "\n";
    }
    return 0;
}

转载于:https://www.cnblogs.com/luoyibujue/p/10668838.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值