AC 自动机+DP……F[L][J]表示长度为L的基因在J的位置的个数。因为基因要变短,转移时要讨论L是否小于J位置串长度,转移到fail指针的位置。
(因为一个白痴错误debug了一个晚上……切记要转移病毒中的病毒啊!)
#include <iostream>
#include <cstring>
using namespace std;
#define CC(A,x) memset(A, x, sizeof(A))
#define FOR(i,n) for(int i=0; i<n; i++)
const int NN=2000, CH=4, MOD=10007;
struct Trie{
inline int sw(char *c){return *c-'a';}
void init(){CC(chd,0); CC(F,0); CC(W,0); sz=1;}
void insert(char *s, int val){
int p=0, dis=0;
for (; *s; p=chd[p][sw(s++)]){
if (!chd[p][sw(s)]) chd[p][sw(s)]=sz++;
D[p] = dis++;
}
W[p]=val; D[p]=dis;
}
void AC(){
int Q[NN], *b=Q, *e=Q, v;
FOR(i,CH) if (v=chd[0][i]) *e++ = v;
for (int p=*b; b!=e; p=*++b)
FOR(i,CH) if (v=chd[p][i]){
F[*e++ = v] = chd[F[p]][i];
if (W[F[v]]) W[v]=1;
}else chd[p][i] = chd[F[p]][i];
}
int find(char *s){
int p = 0;
for (; *s; p=chd[p][sw(s++)]);
return p;
}
int chd[NN][CH], F[NN], W[NN], D[NN], sz;
}trie;
int P, N;
char str[256], ss[32];
void Input(){
trie.init();
cin>>str>>P>>N;
FOR(i,N) {
cin>>ss;
trie.insert(ss, 1);
}
trie.AC();
}
int F[2][110][NN]={0}, S=0, D=1;
void DP(){
int pos = trie.find(str);
int len = strlen(str);
F[S][len][pos] = 1;
if (trie.W[pos]) {cout<<"0 1"<<endl; return;}
int old=0, ill=0, add;
while (P--){
CC(F[D], 0);
FOR(j, trie.sz){
if (trie.W[j]) continue;
for(int L=1; L<=100; L++){
if ((add=F[S][L][j]) == 0) continue;
FOR(k,CH){
int son = trie.chd[j][k];
F[D][L+1][son] += add;
F[D][L+1][son] %= MOD;
if (trie.W[son]){
ill+=add, ill%=MOD;
}
}
if (L == 1){
old += add;
old %= MOD;
}else if (L <= trie.D[j]){
int x = trie.F[j];
F[D][L-1][x] += add;
F[D][L-1][x] %= MOD;
}else{
F[D][L-1][j] += add;
F[D][L-1][j] %= MOD;
}
}
}
D=S; S=1-S;
}
cout<<old<<" "<<ill<<endl;
}
int main()
{
Input();
DP();
return 0;
}