[Luogu P4052] [BZOJ 1030] [JSOI2007]文字生成器
阿新 • • 發佈:2018-11-25
洛谷傳送門
BZOJ傳送門
題目描述
JSOI交給隊員ZYX一個任務,編制一個稱之為“文字生成器”的電腦軟體:該軟體的使用者是一些低幼人群,他們現在使用的是GW文字生成器v6版。
該軟體可以隨機生成一些文章―――總是生成一篇長度固定且完全隨機的文章—— 也就是說,生成的文章中每個位元組都是完全隨機的。如果一篇文章中至少包含使用者們瞭解的一個單詞,那麼我們說這篇文章是可讀的(我們稱文章a包含單詞b,當且僅當單詞b是文章a的子串)。但是,即使按照這樣的標準,使用者現在使用的GW文字生成器v6版所生成的文章也是幾乎完全不可讀的?。ZYX需要指出GW文字生成器 v6
生成的所有文字中可讀文字的數量,以便能夠成功獲得v7更新版。你能幫助嗎?
輸入輸出格式
輸入格式:
輸入檔案的第一行包含兩個正整數,分別是使用者瞭解的單詞總數 ,GW文字生成器 v6生成的文字固定長度 ;以下N行,每一行包含一個使用者瞭解的單詞。這裡所有單詞及文字的長度不會超過 ,並且只可能包含英文大寫字母
輸出格式:
一個整數,表示可能的文章總數。只需要知道結果模 的值。
輸入輸出樣例
輸入樣例#1:
2 2
A
B
輸出樣例#1:
100
解題分析
自動機上 , 求出沒有給定字串的個數, 再用 去減就好了。
程式碼如下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <cstdlib>
#include <algorithm>
#include <queue>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MOD 10007
#define MX 10050
int son[MX][26], fail[MX];
std::queue <int> q;
bool tag[MX];
char buf[MX];
int dp[105][MX];
int cnt, root, n, num;
IN int fpow(R int base, R int tim)
{
int ret = 1; base %= MOD;
W (tim)
{
if (tim & 1) ret = 1ll * ret * base % MOD;
base = 1ll * base * base % MOD, tim >>= 1;
}
return ret;
}
IN void add(R int ad, int &tar) {tar += ad; if (tar >= MOD) tar -= MOD;}
void insert()
{
R int len = std::strlen(buf), now = root, id;
for (R int i = 0; i < len; ++i)
{
id = buf[i] - 'A';
if (!son[now][id]) son[now][id] = ++cnt;
now = son[now][id];
}
tag[now] = true;
}
void build()
{
R int now = root, tar;
for (R int i = 0; i < 26; ++i) if (son[now][i]) q.push(son[now][i]);
W (!q.empty())
{
now = q.front(); q.pop();
for (R int i = 0; i < 26; ++i)
{
if (son[now][i])
{
fail[son[now][i]] = son[fail[now]][i];
tag[son[now][i]] |= tag[fail[son[now][i]]];
q.push(son[now][i]);
}
else son[now][i] = son[fail[now]][i];
}
}
}
void DP()
{
R int i, j, k, nex;
dp[0][0] = 1;
for (i = 0; i < n; ++i)
{
nex = i + 1;
for (j = 0; j <= cnt; ++j)
for (k = 0; k < 26; ++k)
if (!tag[son[j][k]]) add(dp[i][j], dp[nex][son[j][k]]);
}
int ans = 0;
for (i = 0; i <= cnt; ++i) add(dp[n][i], ans);
printf("%d", (fpow(26, n) - ans + MOD) % MOD);
}
int main(void)
{
scanf("%d%d", &num, &n);
W (num--) scanf("%s", buf), insert();
build(); DP();
}