[LuoguP3808] 【模板】AC自动机(简单版)数组版

待填坑

Code

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int N=1000000+1000;
struct AC_AutoMation
{
    #define root 0
    static const int sigma_size=26;
    struct node
    {
        int nxt[sigma_size],sum,fa,fail;
    }t[N*5];
    int tot;
    void Insert(char c[])
    {
        int now=root,len=strlen(c+1);
        for(int i=1;i<=len;i++)
        {
            if(t[now].nxt[c[i]-‘a‘]==0)
                t[now].nxt[c[i]-‘a‘]=++tot;
            now=t[now].nxt[c[i]-‘a‘];
        }
        t[now].sum++;
    }
    void Build()
    {
        queue <int> Q;
        for(int i=0;i<sigma_size;i++)
            if(t[root].nxt[i]!=0)
                Q.push(t[root].nxt[i]);
        while(!Q.empty())
        {
            int now=Q.front();
            Q.pop();
            for(int i=0;i<sigma_size;i++)
                if(t[now].nxt[i]!=0)
                {
                    int temp=t[now].fail;
                    while(t[temp].nxt[i]==0 and temp!=root)
                        temp=t[temp].fail;
                    t[t[now].nxt[i]].fail=t[temp].nxt[i];
                    Q.push(t[now].nxt[i]);
                }
        }
    }
    int Query(char c[])
    {
        int ans=0,len=strlen(c+1),now=root;
        for(int i=1;i<=len;i++)
        {
            int x=c[i]-‘a‘;
            while(t[now].nxt[x]==0 and now!=root) now=t[now].fail;
            now=t[now].nxt[x];
            int temp=now;
            while(temp!=root)
            {
                if(t[temp].sum>=0)
                {
                    ans+=t[temp].sum;
                    t[temp].sum=-1;
                    temp=t[temp].fail;
                }
                else break;
            }
        }
        return ans;
    }
    #undef root
}trie;
int n;
char c[N];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",c+1);
        trie.Insert(c);
    }
    trie.Build();

    scanf("%s",c+1);
    printf("%d",trie.Query(c));
    return 0;
}

原文地址:https://www.cnblogs.com/GoldenPotato/p/8747017.html

时间: 2024-08-29 03:00:15

[LuoguP3808] 【模板】AC自动机(简单版)数组版的相关文章

字典树模板( 指针版 &amp;&amp; 数组版 )

模板 : #include<string.h> #include<stdio.h> #include<malloc.h> #include<iostream> #include<algorithm> using namespace std; const int maxn = 26; struct Trie { Trie *Next[maxn]; int v; inline void init(){ this->v = 1; for(int

【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序

[题意]阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后). l 按一下印有'B'的按键,打字机凹槽中最后一个字母会消失. l 按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失. 我们把纸上打印出来的字符串从1开始顺序编号,一直到n.打字机有一个非

算法模板——AC自动机

实现功能——输入N,M,提供一个共计N个单词的词典,然后在最后输入的M个字符串中进行多串匹配(关于AC自动机算法,此处不再赘述,详见:Aho-Corasick 多模式匹配算法.AC自动机详解.考虑到有时候字典会相当稀疏,所以引入了chi和bro指针进行优化——其原理比较类似于邻接表,这个东西本身和next数组本质上是一致的,只是chi和bro用于遍历某一节点下的子节点,next用于查询某节点下是否有需要的子节点) 1 type 2 point=^node; 3 node=record 4 ex:

tyvj P1519 博彩游戏(AC自动机+DP滚动数组)

P1519 博彩游戏 背景 Bob最近迷上了一个博彩游戏…… 描述 这个游戏的规则是这样的:每花一块钱可以得到一个随机数R,花上N块钱就可以得到一个随机序列:有M个序列,如果某个序列是产生的随机序列的子串,那么就中奖了,否则不中.Bob会告诉你这M个序列,和身上有的钱的总数N,当然还有R的范围.请你告诉Bob中奖的概率有多少? 输入格式 第一行三个用空格隔开的数N.M和R的范围R.其中1<=R<=9,0<N<=60,0<M<=20000.下面M行每行一个字符串(长度小于

bzoj 2434 AC自动机+树状数组

2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 3493  Solved: 1909[Submit][Status][Discuss] Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽

HDU 6096 String(AC自动机+树状数组)

题意 给定 \(n\) 个单词,\(q\) 个询问,每个询问包含两个串 \(s_1,s_2\),询问有多少个单词以 \(s_1\) 为前缀, \(s_2\) 为后缀,前后缀不能重叠. \(1 \leq n,q \leq 10^5\) 思路 字符串题有一个小技巧,拼接字符串,中间加上连接符.如这道题,可以将查询变成 \(s_2+\text{\{}+s_1\) 的形式,相应的,把单词 \(T\) 变为 \(T+\text{\{}+T\) 的形式.那么就是普通的匹配问题了. 对于询问建立\(\text

[模板][P3808]AC自动机(简单版)

模板,详见代码: #include<bits/stdc++.h> using namespace std; const int mxn=1e7+5; char str[mxn],p[80]; queue<int > q; namespace Trie { int tot,fail[mxn],val[mxn]; int t[mxn][26]; void ins(char *s) { int len=strlen(s),u=0; for(int i=0;i<len;++i) {

[模板]洛谷T3808 AC自动机(简单版)

1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 #include<ctime> 6 #include<cstdlib> 7 8 #include<string> 9 #include<stack> 10 #include<queue> 11 #include<vector> 1

CF587F Duff is Mad(AC自动机+树状数组+分块)

考虑两一个暴力 1 因为询问\([a,b]\)可以拆成\([1,b]\)-\([1,a-1]\)所以把询问离线,然后就是求\([1,x]\)中被\(S_i\)包含的串的数量.考虑当\([1,x-1]->[1,x]\)时我们把\(S_x\)结束节点在fail树的子树加1.然后询问就是求\(S_i\)在AC自动机上跑时经过所有点的点权用树状数组维护.设\(\sum{len[S_i]}=L\)这样的复杂度就是\(O(mLlogL)\)无法通过此题. 2 依然离线.这次我们把\(S_i\)放在fail树

BZOJ2434 NOI2011 阿狸的打字机 AC自动机+树状数组+DFS序

题意:给定三个操作:1.在当前字符串的末尾添加一个字符c  2.在当前字符串的末尾删除一个字符  3.记录当前字符串并对其标号.再给出N组询问,每组询问需回答第x个字符串在第y个字符串中出现的次数 题解: 首先按照如下规则建Trie,设当前节点为t,第i个字符串的结尾在Trie中的位置为mark[i]: 1.插入操作:看t是否有c这个儿子,有则t=t->child[c],否则t->child[c]=NewNode,t=t->child[c] 2.删除操作:t=t->father 3