首页 > 其他分享 >ac自动机

ac自动机

时间:2022-08-23 02:55:25浏览次数:133  
标签: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,自动机
From: https://www.cnblogs.com/liang302/p/16614796.html

相关文章

  • [JSOI2007]文本生成器【AC自动机+DP】
    下定决心想要将这份爱意传达给你,与你在一起的每一刻总是那么值得珍藏,你的存在左右着我的思绪,实在是不想错过这样的美好,真的不和我在一起吗?我的学术生涯,虽然有点奇妙,......
  • PlantUML 安装与使用(Mac/Idea)
    1.安装确保本机可以使用brew指令brewinstallgraphviz出现以上提示去Homebrew官网:https://brew.sh/index_zh-cn先安装macOS(或Linux)缺失的软件包的管理器,若......
  • ubuntu20.04虚拟机最小化安装(legacy server+xfce4,装完只有3G)
    server自己配桌面,可以最小化安装。legacyserver比liveserver更小,虚拟机用来部署编译环境最好了。其实还有更小的ubuntu-base版,但是那个安装配置太麻烦了。 1.下载ub......
  • react三大核心之一props
    -html标签可以在标签上写自定义属性,那么react的组件,也可以像传属性一项,给组件传props;react组件接收到传入的属性后,会自动塞进实例的props属性中,通过this.props可以拿到外......
  • React报错之React Hook 'useEffect' is called in function
    正文从这开始~总览为了解决错误"ReactHook'useEffect'iscalledinfunctionthatisneitheraReactfunctioncomponentnoracustomReactHookfunction",可以将......
  • 实现最简单的 React DOM Diff 算法
    实现最简单的ReactDOMDiff算法本文写于2022年08月22日定义VNode与VNodeList类型首先我们定义一个简单的VNode类型。typeFlag="Placement"|"Delet......
  • Docke 搭建 apache2 + php8 + MySQL8 环境
    Docker安装执行Docker安装命令curl-fsSLhttps://get.docker.com/|sh启动Docker服务sudoservicedockerstart查看Docker是否正常工作sudo......
  • RBAC权限模型:控制不同用户的菜单权限
    RBAC权限模型控制不同用户的菜单权限:权限:权限,是用户可以访问的资源。包括页面权限、操作权限和数据权限。页面权限:页面权限,即用户登录系统可以看到的页面。由菜单控制......
  • oracle时间对比报错:ORA-01861 文字与格式字符串不匹配
    前段时间写一个简单的需求时碰到的,在使用传入的时间参数与oracle数据库里存的时间进行比较时报错,具体错误如下:   在Oracle中,需要使用to_date格式化时间,再进行对比......
  • 使用foreach 实现sql 拼接
    有时候写sql时,需要根据传入的参数构建sql语句,实现遍历集合,构建in条件语句或者批量操作语句,此时可以使用foreach实现对sql的拼接。下面是foreach标签的各个属性属性......