解题思路:
首先按照正常的思路将自动机模型建立起来。
然后就在上面进行DP其中DP[i][j][k].i表示字符串的字符的个数j表示的是最后一位是什么状态.k表示magic string的状态这是用状态压缩记录的也就是2^10。通过每一位01表示该个magic string是否被表示。
这道题开始的时候是TLE,是memset的问题。改了之后就狂WA。后来找到了WA的原因,但是没有办法改。因为对于3 2 2 she he这样的数据没有办法过。最开始的想法是将状态之间的关系记录在g[maxn][maxn] 。然后每次加入一个状态就判断这个状态表示的字符串是否为magic string 如果是 则记录。但是后来发现这样写会有一个很严峻的问题。比如she he 那样的例子就不能得到解。后来看了其他人的代码。发现他们对于每一个状态就加入了tag数组,记录该状态下的字符串包含多少的magic string。
上代码:
#include<cstdio>
#include<cstring>
using namespace std;
struct node{
node *fail;
node *next[26];
int count;
int id;
bool end;
int tag;
node(){
id=0;
end=false;
fail=NULL;
count=0;
tag=0;
for(int i=0;i<=25;i++){
next[i]=NULL;
}
}
};
const int MAXN=110;
node *T[110];
node *q[500010];
node *root=new node();
int num=1;
void insert(char word[],int pp){
node *cur=root;
int i=0,branch;
while(word[i]){
branch=word[i]-'a';
if(cur->next[branch]==NULL){
cur->next[branch]=new node();
T[num]=cur->next[branch];
cur->next[branch]->id=num++;
}
i++;
cur=cur->next[branch];
}
cur->end=true;
cur->count++;
cur->tag=1<<pp;
}
void AC(){
int rear=1,front=0,i;
node *cur;
q[0]=root;
root->fail=root;
while(front!=rear){
node *p=q[front++];
p->end=p->end||p->fail->end;
for(int i=0;i<=25;i++){
if(p->next[i]==NULL){
if(p==root)
p->next[i]=root;
else
p->next[i]=p->fail->next[i];
}
else{
if(p==root)
p->next[i]->fail=root;
else{
p->next[i]->fail=p->fail->next[i];
p->next[i]->tag=p->next[i]->tag|p->fail->next[i]->tag;
}
q[rear++]=p->next[i];
}
}
}
}
int magic[110],g[MAXN][MAXN];
int nnum=0;
void get_matrix(){
int i,j;
memset(g,0,sizeof(g));
memset(magic,0,sizeof(magic));
for(int i=0;i<num;i++){
for(int j=0;j<=25;j++){
if(T[i]->next[j]!=NULL)
g[i][T[i]->next[j]->id]++;
}
if(T[i]->end==true){
magic[i]=++nnum;
}
}
}
int dp[30][110][1300];
int f[20];
void ini(){
f[0]=1;
for(int i=1;i<=10;i++){
f[i]=2*f[i-1];
}
}
int mod=20090717;
int gg[MAXN][MAXN];
main(){
int n,m,kk;
char s[20];
while(scanf("%d%d%d",&n,&m,&kk)!=-1 && !(n==0 && m==0 && kk==0)){
num=1;nnum=0;root=new node();
for(int i=1;i<=m;i++){
scanf("%s",s);
insert(s,i-1);
}
AC();
T[0]=root;
root->id=0;
get_matrix();
for(int i=0;i<=n;i++)
for(int j=0;j<=num;j++)
for(int k=0;k<=1024;k++)
dp[i][j][k]=0;
ini();
dp[0][0][0]=1;
for(int i=0;i<num;i++){
gg[i][0]=0;
for(int j=0;j<num;j++){
if(g[i][j]!=0){
gg[i][++gg[i][0]]=j;
}
}
}
for(int i=0;i<=n-1;i++){
for(int j=0;j<num;j++){
for(int k=0;k<=1023;k++){
if(dp[i][j][k]!=0){
for(int x=1;x<=gg[j][0];x++){
int cnt=T[gg[j][x]]->tag;
dp[i+1][gg[j][x]][k|cnt]+=(dp[i][j][k]*g[j][gg[j][x]])%mod;
dp[i+1][gg[j][x]][k|cnt]=dp[i+1][gg[j][x]][k|cnt]%mod;
}
}
}
}
}
int ans=0;
for(int i=0;i<num;i++){
for(int j=0;j<=1023;j++){
int flag=0;
for(int k=0;k<=9;k++){
int tmp=f[k]|j;
if(tmp==j)
flag++;
}
if(flag>=kk && dp[n][i][j]!=0){
ans+=dp[n][i][j];
ans=ans%mod;
}
}
}
printf("%d\n",ans%mod);
}
}