浅谈AC自动机

AC自动机是一种字符串算法,用于在一个文本串中匹配多个模式串并找出它们的所有位置。通过建立trie树和fail指针,即使匹配失败也能高效地转向其他可能的匹配路径。在实现上,包括建树、预处理fail指针和实际操作步骤,其时间复杂度为O(n)。
摘要由CSDN通过智能技术生成

0.前言

第一眼看,还以为是自动AC机,学了就可以ak虐全场了。
可惜理想很丰满,现实却很骨感,它叫AC自动机,是一种字符串算法
我们都知道KMP算法是可以在一个文本串中找到你想找的一个模式串的位置的,
而AC自动机的主要用处就在于可以把多个模式串匹配到文本串中,并且可以找到一个模式串出现的所有位置,好高级呀。
预备知识:
trie树就够了

一.思想

我们先对所有需要匹配的模式串建立trie树,
然后要建立fail指针,指向与当前后缀相等的前缀,来一张图帮助理解:
在这里插入图片描述
虚线就是我们的fail指针,首先所有开头的字母都指向根。然后,图中h指向另一个子树的h是因为另一个字符串的前缀sh与我当前的后缀sh一样,其他的指针同理。
有了这个东西,当我们匹配不下去的时候,就可以转向fail指针指向的那个节点继续查找,这个时间复杂度就很低。
这就是AC自动机的主要思想。
时间复杂度: O ( n ) O(n) O(n)

二.实现

1.建树

建trie树就不用我说了吧

void insert (char *a){
   
    int len = strlen (a), now = 0;
    for (int i = 0; i < len; i ++){
   
        if (! tire[now][a[i] - 'a'])
            tire[now][a[i] - 'a'] = ++ cnt;
        now = tire[now][a[i] - 'a'];
    }
    cntword[now] ++;//记录当前节点有多少个完整的模式串
}

2.预处理fail

这里我们要用bfs,搜索这颗trie树
注意:这个节点的fail要么等于它父亲节点的fail的后一个,要么就是0.

void getfail (){
   
    queue <int> Q;
    for (int i = 0; i < 26; i ++){
   //先把所有模式串的开头扔进队列
        if (tire[0][i]){
   
           
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
后缀自动机被广泛应用于OI竞赛中,特别是在字符串相关的问题中。它是一种高效的数据结构,能够有效地解决各种字符串匹配、模式匹配和计数等问题。 首先,后缀自动机可以用于解决最长公共子串和最长公共子序列等问题。对于给定的两个字符串,可以将其加入到后缀自动机中,并通过动态规划的方式求解最长公共子串或子序列的长度。 其次,后缀自动机还可以用于解决多次询问下的子串出现次数问题。通过构建全局后缀自动机,可以在O(n)的时间复杂度内预处理字符串,并在O(m)的时间复杂度内得出任意子串的出现次数,其中n为字符串长度,m为询问总数。 另外,后缀自动机还可以用于解决包含多模式匹配的问题。通过将模式串加入到后缀自动机中,并预处理自动机的fail指针,可以在O(n)的时间复杂度内找到所有模式串在文本中的出现位置。这在处理大规模的文本匹配问题时非常有用。 此外,后缀自动机还可以进行字符串的字典序统计。通过在构建自动机时记录每个节点的信息,可以在O(n)的时间复杂度内得到字符串的字典序第k小/大的子串。 总之,后缀自动机在OI竞赛中有着广泛的应用,能够解决各种字符串相关的问题。通过巧妙地构建自动机,并充分利用其性质,可以实现高效的字符串算法,为解决复杂的字符串问题提供了有力的工具。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值