P4052 文本生成器
P4052 文本生成器
题意:
给出n个单词,求至少包含其中一个单词的固定长度的文章的数量。
思路:
如果是求,怎么组成使得一个子串都没有的话,就很好求,如果当前位置到达了,单词末尾的话,就舍掉就可以了,但是,这里是求至少包含一个单词的固定长度的文章的数量,怎么办呢?
相当一个字符串,要么就是至少包含一个单词的要么就是不包含的,所以拿总的数量-一个都不包含的数量,得到就是最终题目所求的数量。
实现:
#include <stdio.h>
#include <algorithm>
#include <cstring>
using namespace std;
const long long N = 10005, mod = 1e4 + 7;
long long tr[N][26], cnt[N], idx = 1, nex[N], q[N];
char s[N];
//到第i位,匹配到j
long long f[105][N];
void insert() //字典树中插入字符串
{
long long p = 0;
long long len = strlen(s + 1);
for (long long i = 1; i <= len; i++)
{
long long t = s[i] - 'A';
if (!tr[p][t])
tr[p][t] = idx++;
p = tr[p][t];
}
cnt[p] = 1;
}
//构造nex数组
void build()
{
long long hh = 1, tt = 0;
for (long long i = 0; i < 26; i++)
if (tr[0][i])
q[++tt] = tr[0][i];
while (hh <= tt)
{
long long t = q[hh++];
for (long long i = 0; i < 26; i++)
{
//注意下面要改变tr[t][i]值,所以要加引号
long long &p = tr[t][i];
if (!p)
p = tr[nex[t]][i];
else
{
nex[p] = tr[nex[t]][i];
q[++tt] = p;
cnt[p] |= cnt[nex[p]];
}
}
}
}
int main()
{
long long n, m;
scanf("%lld%lld", &n, &m);
for (long long i = 1; i <= n; i++)
{
scanf("%s", s + 1);
insert();
}
build();
f[0][0] = 1;
for (long long i = 1; i <= m; i++)
for (long long j = 0; j < idx; j++)
for (long long k = 0; k < 26; k++)
{
if (cnt[tr[j][k]])
continue;
f[i][tr[j][k]] = (f[i - 1][j] + f[i][tr[j][k]]) % mod;
}
long long res = 0;
for (long long i = 0; i < idx; i++)
res = (res + f[m][i]) % mod;
long long sum = 1;
for (long long i = 1; i <= m; i++)
sum = (sum * 26) % mod;
printf("%lld\n", ((sum - res) % mod + mod) % mod);
return 0;
}