AC自动机的一些处理方法

一些经典的问题:
  1. 求各个模式串在文本串中出现了几次:

    方法: 在AC自动机上先跑一边文本串,记录一下每个点被经过的次数,那么单词被经过的次数就是他的结尾在fail树中的子树的权值和

  2. 找是否有一个匹配不上匹配串的环:

    方法: 把所有能匹配上匹配串的节点匹配记录下来,dfs从跟开始走所有我可以走的点,如果我走到了一个之前走过的点就说明出环了

    实现: 一边调用fail一边更新当前点是否能走,因为fail记录的是前缀等于后缀,后缀深度一定比前缀大,所以fail一定在之前就走过了

  3. (n)个串总共出现(m)次的最短长度

    方法: 求两两单词结尾之间的最短距离,初始矩阵(a_{i,j})表示结尾(i)和结尾(j)之间不经过其他结尾的最短距离,矩阵快速幂(m-1)

    更新成(a_{i,j})表示结尾(i)到结尾(j)之间经过其他(m-2)个结尾的最小距离,现在总共经过了(m)个单词结尾,再加上第一个单词的长度,就是最短长度,一共(nm)种情况取最小的一种

  4. 每次删掉文本串中的最早出现的模式串,剩下的字符继续拼在一起

    方法: 跑AC自动机,模拟栈,发现匹配到一个单词,把属于这个单词的字符全部弹出,继续从之前匹配的位置继续往下找

注意问题:
  1. 在fail树上拓排的时候在更新fail指针的时候进行,如:
      fail[trie[root][i]] = trie[fail[root]][i];
      du[trie[fail[root]][i]] ++;
  1. 看当前字符是否能匹配上匹配串是在调用fail的时候进行,如:
      trie[root][i] = trie[fail[root]][i];
      vis[trie[root][i]] |= vis[trie[fail[root]][i]];
原文地址:https://www.cnblogs.com/little-uu/p/14051581.html