AC自动机(跟算法提高课学的

文章详细讲解了算法提高课程中的Trie数据结构、KMP算法和AC自动机模型的应用,包括优化思路,以及如何在DNA修复问题中使用这些技术。作者提供了示例代码和关键步骤解析。
推荐:

AcWing 1282. 搜索关键词(Trie+KMP+bfs)
AcWing 1053. 修复DNA【线性DP+AC自动机模型+优化思路】

讲的很清楚,基本上把算法提高课这一节的内容,从KMP到AC自动机到优化版都讲明白了(虽然我还不是很懂但讲的比我好比我详细,强推!)

(而且我修复DNA的代码还是跟着打的…嗯可以直接看这俩链接不用往下看了


KMP求next数组:

next[0] = next[1] = 0;
for (int i = 2; i <= m; i++)
{
   
   
	int j = next[i - 1];
	while (j && p[i] != p[j + 1]) j = next[j];
	if (s[i] == p[j + 1]) j++;
	next[i] = j;
}

改成AC自动机时,将链式结构对应到树形结构,这里的一个字母对应同深度的所有节点,算第i层用到前i-1层信息,应该按深度遍历

while (队列不为空)
{
   
   
	t = q[hh + 1];//对应第i - 1层
	for (c = 0; c < 26; c++)//枚举儿子
	{
   
   
		ch = tr[t, c];//对应第i层
		j = next[t];
		while (j && !tr[j, c])//j的儿子不存在c
			j = next[j];
		if (tr[j, c]) j = tr[j, c];
		next[ch] = j;
		把ch加入队列
	}
}

题目:AcWing1282. 搜索关键词

(没买算法提高课的别看了做不了)

代码:(手写queue写少了条件写成了h < t以及遍历时条件用了i < strlen(str)导致一直超时我真的不知道为啥T^T)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;

const int N = 10005, M = 1000005, S = 55;

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

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

void build()
{
   
   
    int h = 0, t = -1;
    for (int i = 0; i < 26; i++)
        if (tr[0][i]) q[++t] = tr[0][i];
    
    while (h <= t)
    {
   
   
        int x = q[h++];
        for (int i = 0; i < 26; i++)
        {
   
   
            int ch = tr[x][i];
            if (!ch) continue;
            int j = ne[x];
            while (j && !tr[j][i]) j = ne[j];
            if (tr[j][i]) j = tr[j][i];
            ne[ch] = j;
            q[++t] = ch;
        }
    }
}

int main()
{
   
   
    int T, n;
    scanf("%d", &T);
    while (T--)
    {
   
   
        idx = 0;
        memset(tr, 0, sizeof tr);
        memset(ne, 0, sizeof ne);
        memset(cnt, 0, sizeof cnt);
        
        scanf("%d", &n);
        for (int i = 0; i < n; i++)
        {
   
   
            scanf("%s", str);
            insert();
        }
        scanf("%s", str);
        build(
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值