ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ac自动机

2022-08-23 03:01:02  阅读:143  来源: 互联网

标签:ac int tt tr ++ hh str 自动机


模板

void insert() //建trie树
{
    int p = 0;
    for (int i = 0; str[i]; i ++ )
    {
        int t = str[i] - 'a';
        if (!tr[p][t]) tr[p][t] = ++ idx;
        p = tr[p][t];
    }
    cnt[p] ++ ;
}

void build()
{
    int hh = 0, tt = -1;
    for (int i = 0; i < 26; i ++ )
        if (tr[0][i])
            q[ ++ tt] = tr[0][i];//加入队列
    while(hh<=tt){
	int t=q[hh++];
	for(int i=0;i<26;i++){
		int c=tr[t][i];//看看她的儿子 
		if(!c) continue ;//可能没有 
		int j=next[t];//t这个结点可以向上匹配去到哪个位置 
		while(j&&!tr[j][i]) j=next[j];//如果j对应的第i个字符不存在说明没有找到相同的后缀 所以要再次跳转 
		if(tr[j][i]) j=tr[j][i];//最后如果找到了儿子 那么就走过去	 
		next[c]=j;//让next c等于那个字符  c是idx 
		q[++t]=c//多加一个idx 
	}
}


t= str[i]-'a'; 
for(int i=0,j=0;str[i];i++){
	int t=str[i]-'a';
	while(j&&!tr[j][t]) j=ne[j];//不存在这个结点就挑走 
	if(tr[j][t]) j=tr[j][t];//存在就走过去 找到匹配到最靠下的结点
	 
	
}

优化防止卡到

void build()
{
    int hh = 0, tt = -1;
    for (int i = 0; i < 26; i ++ )
        if (tr[0][i])
            q[ ++ tt] = tr[0][i];//加入队列
    while(hh<=tt){
	int t=q[hh++];
	for(int i=0;i<26;i++){
		int p=tr[t][i];//看看她的儿子 
		if(!c) tr[t][i]=tr[ne[t]][i] ;//如果不存在 直接存下next应该走到的位置 下次不需要在词条 
		else{
                  ne[p]=tr[ne[t]][i];
                  q[++t]=p;
                  }
                 
             }

}
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 10010, S = 55, M = 1000010;

int n;
int tr[N * S][26], cnt[N * S], idx;
char str[M];
int q[N * S], ne[N * S];

void insert()
{
    int p = 0;
    for (int i = 0; str[i]; i ++ )
    {
        int t = str[i] - 'a';
        if (!tr[p][t]) tr[p][t] = ++ idx;//赋值一个结点
        p = tr[p][t];
    }
    cnt[p] ++ ;
}

void build()
{
    int hh = 0, tt = -1;
    for (int i = 0; i < 26; i ++ )
        if (tr[0][i])
            q[ ++ tt] = tr[0][i];//队列 因为上面的操作 树已经建好了 这里看看根节点下面的对应字母 统计出第一层的各个结点

    while (hh <= tt)
    {
        int t = q[hh ++ ];
        for (int i = 0; i < 26; i ++ )
        {
            int p = tr[t][i];
            if (!p) tr[t][i] = tr[ne[t]][i];//如果不村子啊 直接跳到对应的最下方 下次直接用
            else
            {
                ne[p] = tr[ne[t]][i];
                q[ ++ tt] = p;
            }
        }
    }
}

int main()
{
    int T;
    scanf("%d", &T);
    while (T -- )
    {
        memset(tr, 0, sizeof tr);
        memset(cnt, 0, sizeof cnt);
        memset(ne, 0, sizeof ne);
        idx = 0;

        scanf("%d", &n);
        for (int i = 0; i < n; i ++ )
        {
            scanf("%s", str);
            insert();
        }

        build();

        scanf("%s", str);

        int res = 0;
        for (int i = 0, j = 0; str[i]; i ++ )
        {
            int t = str[i] - 'a';
            j = tr[j][t];

            int p = j;
            while (p)
            {
                res += cnt[p];
                cnt[p] = 0;
                p = ne[p];
            }
        }

        printf("%d\n", res);
    }

    return 0;
}


标签:ac,int,tt,tr,++,hh,str,自动机
来源: https://www.cnblogs.com/liang302/p/16614796.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有