keywords search (hdu 2222 AC自动机模板题)

AC自动机模板题:keywords search

网上说AC自动机的前置技能需要学习字典树和KMP,可我的感觉和KMP关系不太大,和字典树的数据结构类型关系倒是有密切联系,一定是我太菜了,所以理解不是那么深刻

AC自动机的关键:失配指针的构造

fail指针的构造是由bfs()分层遍历完成的,首先我们先将第一层压入队列,第一层的fail[]:0节点,然后寻找下一层的失配指针,下一层的失配指针,在上一层父亲的失配指针的孩子是否有和下一层相同的孩子,如果有则是,如果没有则往上找,直到0节点结束,这里的思想和KMP的类似,新层的点需要压入队列,而旧层的点用过,删除掉即可

AC代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=1e6+5;
const int alph=26;
int tir[500005][26];//前缀树
int fail[500005];//fail指针
char str[maxn],s[maxn];
int sum[500005];
int cnt;//计数器
void inser(char*str)
{
    int len=strlen(str);
    int root=0;
    for(int i=0; i<len; i++)
    {
        int id=str[i]-'a';
        if(!tir[root][id])
        {
            tir[root][id]=++cnt;
        }
        root=tir[root][id];
    }
    sum[root]++;
}
void getfail()//构造fail指针
{
    queue<int>q;
    int root=0;
    fail[0]=0;
    for(int i=0; i<alph; i++)
    {
        if(tir[root][i])
        {
            fail[tir[root][i]]=0;
            q.push(tir[root][i]);
        }
    }
    while(!q.empty())
    {
        //printf("1\n");
        int r=q.front();
        q.pop();
        for(int i=0;i<alph;i++)
        {

                int u=tir[r][i];
                if(u)
                {
                    q.push(u);
                    int v=fail[r];
                    while(v&&!tir[v][i])
                        v=fail[v];
                    fail[u]=tir[v][i];
                }
        }
    }
}
int match(char *s)
{
    int len=strlen(s);
    int root=0;
    int ans=0;
    for(int i=0;i<len;i++)
    {
         int c=s[i]-'a';
         while(root&&!tir[root][c])
              root=fail[root];
         root=tir[root][c];
         int tem=root;
         while(tem&&sum[tem])
         {
             ans+=sum[tem];
             sum[tem]=0;
             tem=fail[tem];
         }
    }

    return ans;
}
int main()
{

    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        cnt=0;
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
        {
            scanf("%s",str);
            inser(str);
        }
        getfail();
        scanf("%s",s);
        printf("%d\n",match(s));
        memset(sum,0,sizeof(sum));
        memset(tir,0,sizeof(tir));
    }
}
发布了205 篇原创文章 · 获赞 12 · 访问量 8511

猜你喜欢

转载自blog.csdn.net/yangzijiangac/article/details/103861620
今日推荐