AC自动机 + DP + 大数。网上说矩阵过不去,写了一发样例都没调出来直接放弃了。由于习惯性的把数组开大了,爆了两次,然后直接A了。注意大数为0的输出
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
#define N 2005
#define INF 1000000009
typedef long long LL;
int n;
int letter[300];
struct Trie {
Trie *fail;
Trie *son[300];
int kind, isword;
}s[N];
Trie *que[N];
int ptr;
int id(unsigned char x){
return letter[x];
}
Trie *NewNode(){
Trie *p = &s[ptr];
for(int i = 0; i < n; i++)p->son[i] = NULL;
p->fail = NULL;
p->isword = 0;
p->kind = ptr++;
return p;
}
void Insert(unsigned char *c, Trie *root){
Trie *tmp = root;
for(int i = 0; c[i]; i++){
if(tmp->son[id(c[i])] == NULL) tmp->son[id(c[i])] = NewNode();
tmp = tmp->son[id(c[i])];
}
tmp->isword = 1;
}
void Build_fail(Trie *root){
Trie *tmp;
int head = 0, tail = 0;
que[tail++] = root;
root->fail = NULL;
while(head < tail){
tmp = que[head++];
for(int i = 0; i < n; i++){
if(tmp->son[i]){
if(tmp == root)tmp->son[i]->fail = root;
else {
Trie *p = tmp->fail;
while(p){
if(p->son[i]){
tmp->son[i]->fail = p->son[i];
break;
}
p = p->fail;
}
if(p == NULL)tmp->son[i]->fail = root;
}
if(tmp->son[i]->fail->isword)tmp->son[i]->isword = 1;
que[tail++] = tmp->son[i];
}
else if(tmp == root)tmp->son[i] = root;
else tmp->son[i] = tmp->fail->son[i];
}
}
}
#define length 100
class Bignum{
char s[length * 2];
public :
Bignum(int x = 0){
memset(s, 0, sizeof(s));
s[0] = x;
}
void setnum(int x){
for(int i = 0; x; i++){
s[i] = x % 10;
x /= 10;
}
}
Bignum operator+(Bignum x){
Bignum ans;
for(int i = 0; i < length; i++){
ans.s[i] += s[i] + x.s[i];
ans.s[i + 1] += ans.s[i] / 10;
ans.s[i] %= 10;
}
return ans;
}
void print(){
int i = length;
while(s[i] == 0 && i >= 0)i--;
if(i == -1)printf("0");
while(i >= 0)printf("%d", s[i--]);
printf("\n");
}
}dp[55][105];
void solve(int tot){
dp[0][0].setnum(1);
Bignum zero;
for(int i = 1; i <= tot; i++){
for(int j = 0; j < ptr; j++){
Trie *tmp = &s[j];
if(tmp->isword)continue;
for(int k = 0; k < n; k++){
if(tmp->son[k]->isword)continue;
dp[i][tmp->son[k]->kind] = dp[i][tmp->son[k]->kind] + dp[i - 1][j];
}
}
}
Bignum ans;
for(int i = 0; i < ptr; i++){
ans = ans + dp[tot][i];
}
ans.print();
}
int main(){
int m, p;
while(scanf("%d%d%d", &n, &m, &p) != EOF){
ptr = 0;
Trie *root = NewNode();
unsigned char str[20];
unsigned char ms[55];
scanf("%s", ms);
memset(letter, 0, sizeof(letter));
for(int i = 0; ms[i]; i++)
letter[ms[i]] = i;
for(int i = 0; i < p; i++){
scanf("%s", str);
Insert(str, root);
}
Build_fail(root);
solve(m);
}
return 0;
}