description
jsoi交給隊員zyx乙個任務,編制乙個稱之為「文字生成器」的電腦軟體:該軟體的使用者是一些低幼人群,他們現在使用的是gw文字生成器v6版。該軟體可以隨機生成一些文章―――總是生成一篇長度固定且完全隨機的文章—— 也就是說,生成的文章中每個位元組都是完全隨機的。如果一篇文章中至少包含使用者們了解的乙個單詞,那麼我們說這篇文章是可讀的(我們稱文章a包含單詞b,當且僅當單詞b是文章a的子串)。但是,即使按照這樣的標準,使用者現在使用的gw文字生成器v6版所生成的文章也是幾乎完全不可讀的?。zyx需要指出gw文字生成器 v6生成的所有文字中可讀文字的數量,以便能夠成功獲得v7更新版。你能幫助他嗎?
input
輸入檔案的第一行包含兩個正整數,分別是使用者了解的單詞總數n (<= 60),gw文字生成器 v6生成的文字固定長度m;以下n行,每一行包含乙個使用者了解的單詞。這裡所有單詞及文字的長度不會超過100,並且只可能包含英文大寫字母a..z
output
乙個整數,表示可能的文章總數。只需要知道結果模10007的值。
sample input
2 2a
b sample output
100
題意是給出一些字串,求長為m的包含某些其中串的字串的總數。
我們可以倒過來想,長度為m的字串共有26^m種可能性,如果我們減去不包含任何給定串的字串的個數,剩下的個數就是要求的答案。
所以我們可以先將所有給定的字串構建乙個ac自動機,然後進行dp。
我們設dp[i][j]表示dp到長度為i的串,且在ac自動機j節點上的值。我們可以清楚的知道我們要從dp[i][j]轉移到dp[i+1][p],其中p為下乙個位置。我們列舉k為a~z這26個字元,並且在ac自動機上查詢,如果從j往fail[j]跳,能跳到某些節點,有以該節點結尾的子串,則表示dp[i+1][j]是不可行的,因為如果這麼走會使最終的字串中出現題目給定的串。如果不存在這樣的點,就將dp[i+1][next[j][k]]加上dp[i][j],並直接將j變為next[j][k]即可。
最後用快速冪求出26^m,然後減去∑dp[m][x](x為ac自動機上所有點)。
#include
#define md 10007
using namespace std;
intread()
int n,m,cnt,q[10000],dp[105][10000],ans,tot;
string s;
struct nodef[10000];
int pows(int a,int b)
return base%md;
}void build(string s)
}f[pl].sum++;
}void fail()
}int main()
fail();
dp[0][0]=1;
for(int i=0;ifor(int j=0;j<=cnt;j++)
now=f[now].fail;
}if(flag) continue;
now=j;now=f[now].next[k];
dp[i+1][now]=(dp[i+1][now]+dp[i][j])%md;}}
tot=pows(26,m);
for(int i=0;i<=cnt;i++)
ans=(ans+dp[m][i])%md;
printf("%d",(tot-ans+md)%md);
return
0;}
(帶講解)bzoj1030 AC自動機 dp
第一道ac自動機上的dp 題意是給出一些字串,求長為m的字串包含這些的一共有多少個,字符集a z 首先運用補集轉換,轉而求不含這些串的個數,最後用26 m減掉就行 根據輸入的字串建立ac自動機 dp i j 表示當前考慮了i位,當前停留在ac自動機的j號節點 每一次可以由dp i j 轉移到dp i...
AC自動機 建立nlogn個AC自動機
string set queries 題意 給你3種操作,1 加入乙個串到集合中。2 刪除集合中的某乙個串 3 查詢集合中的字串在給定的字串種出現幾次。同乙個串可重複 解法 建立多個ac自動機,用二進位制分組來處理。加入給你21個串 分為 16 4 1,再新增乙個串的時候,即21 1,22 16 4...
AC自動機及字尾自動機
ac自動機是一種基於trie樹的演算法,其本質和kmp上的處理很相似。trie樹結構 kmp轉移思路 ac自動機組要由三個部分組成 trie樹的建立 fail指標的匹配 對ac自動機的詢問 每次建立自動機會有一次初始化 ac自動機類 struct node node結構體 struct ac voi...