(帶講解)bzoj1030 AC自動機 dp

2021-07-27 12:36:26 字數 1437 閱讀 6997

第一道ac自動機上的dp

題意是給出一些字串,求長為m的字串包含這些的一共有多少個,字符集a-z

首先運用補集轉換,轉而求不含這些串的個數,最後用26^m減掉就行

根據輸入的字串建立ac自動機

dp[i][j]表示當前考慮了i位,當前停留在ac自動機的j號節點

每一次可以由dp[i][j]轉移到dp[i+1][k],k是列舉第i+1為後作為j的兒子在ac自動機上的編號

列舉k,就是第i+1為填什麼,然後進行下列操作:

首先看看這位能不能填k,判斷方法是從j開始向fail[j]跳,看是不是有乙個j有乙個k兒子,並且k兒子上還有結束標記,只要有乙個就證明如果i+1位填k就會讓整個字串出現ac自動機上的字串,所以不能填k

如果能放,再看看要修改哪個dp陣列。

還是從j開始向fail[j]跳,如果j有k這個兒子就直接修改dp[i+1][j的k兒子]就好

每次修改要對修改目標加上dp[i][j]

答案是所有dp[m][x](x是所有ac自動機上的節點)的和

** 陣列名稱:

fail:失敗指標

danger:結束標記

tr:trie樹

q:佇列

#include

#include

#include

#include

#include

#define md 10007

using namespace std;

char ch[1000];

int fail[6010],dp[1200][6010],f,ans;

inttr[6010][30],trcnt,danger[6010],i,j,n,m,q[6010],anss=1;

void insert() //建立trie樹

danger[now]=1;

}void acmach() //跑出fail陣列

}}int main()

acmach();

dp[0][1]=1; //初始化

for (i=0;i<=m-1;i++)

for (j=1;j<=trcnt;j++)

now=fail[now];

}if (f==1) continue; //不能放直接跳過

now=j;

while (!tr[now][k]) now=fail[now]; //j向fail[j]跳直到有k兒子

now=tr[now][k];

dp[i+1][now]=(dp[i+1][now]+dp[i][j])%md; //修改}}

for (i=1;i<=m;i++)

for (i=1;i<=trcnt;i++)

ans=(anss-ans+md)%md;

cout<%md;

}

BZOJ1030 AC自動機上的DP

description jsoi交給隊員zyx乙個任務,編制乙個稱之為 文字生成器 的電腦軟體 該軟體的使用者是一些低幼人群,他們現在使用的是gw文字生成器v6版。該軟體可以隨機生成一些文章 總是生成一篇長度固定且完全隨機的文章 也就是說,生成的文章中每個位元組都是完全隨機的。如果一篇文章中至少包含...

AC自動機講解

飄過的小牛 ac自動機簡介 首先簡要介紹一下ac自動機 aho corasick automation,該演算法在1975年產生於貝爾實驗室,是著名的多模匹配演算法之一。乙個常見的例子就是給出n個單詞,再給出一段包含m個字元的文章,讓你找出有多少個單詞在文章裡出現過。要搞懂ac自動機,先得有字典樹t...

AC自動機講解

首先,作為作者的我一定知道你已經會了這兩個演算法 kmp與trie樹,如若不會,可以先學習一下。我在這裡宣告一下ac自動機不是自動ac的演算法,其全稱是aho corasick automaton,是一種著名的多模匹配演算法。其實現類似於trie樹與kmp演算法的結合,是將多個模式串放在trie樹上...