[BZOJ1030] [JSOI2007]文本生成器(AC自动机 + DP)
dp没怎么理解好。。。QAQ
f[i][j]表示长度为i,当前节点为j的方案数
——代码
#include <queue>
#include <cstdio>
#include <cstring>
#define N 100001
#define p 10007
int n, m, cnt, ans, sum = 1;
int next[N][26], fail[N], f[101][N];
bool val[N];
char s[N];
std::queue <int> q;
inline void insert()
{
int i, x, now = 0, m = strlen(s + 1);
for(i = 1; i <= m; i++)
{
x = s[i] - 'A';
if(!next[now][x])
next[now][x] = ++cnt;
now = next[now][x];
}
val[now] = 1;
}
inline void make_fail()
{
int i, now;
for(i = 0; i < 26; i++)
if(next[0][i])
q.push(next[0][i]);
while(!q.empty())
{
now = q.front();
q.pop();
for(i = 0; i < 26; i++)
{
if(!next[now][i])
{
next[now][i] = next[fail[now]][i];
continue;
}
fail[next[now][i]] = next[fail[now]][i];
val[next[now][i]] |= val[next[fail[now]][i]];
q.push(next[now][i]);
}
}
}
int main()
{
int i, j, k;
scanf("%d %d", &n, &m);
for(i = 1; i <= n; i++)
{
scanf("%s", s + 1);
insert();
}
make_fail();
for(i = 1; i <= m; i++) sum = (sum * 26) % p;
f[0][0] = 1;
for(i = 1; i <= m; i++)
for(j = 0; j <= cnt; j++)
{
if(val[j] || !f[i - 1][j]) continue;
for(k = 0; k < 26; k++)
if(!val[next[j][k]])
f[i][next[j][k]] = (f[i][next[j][k]] + f[i - 1][j]) % p;
}
for(i = 0; i <= cnt; i++)
if(!val[i])
ans = (ans + f[m][i]) % p;
printf("%d\n", ((sum - ans) % p + p) % p);
return 0;
}

浙公网安备 33010602011771号