#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string.h>
#include <queue>
#include <vector> //poj1625 ac自动机(dp)---高精度处理(不能用矩阵乘法)
using namespace std;
int n, m, k, vis[200], dp[60][110][100]; //dp数组第一维表示单词长度,第二维表示到达什么节点(位置),第三维表示路径数目(用大数表示)
struct node
{
int isword;
int fail;
int next[50];
void init()
{
for(int t=0; t<50; ++t)
next[t]=0;
isword=0;
fail=-1;
}
}a[110];
void insert(char *p)
{
int t, h, g=0, j=strlen(p);
for(t=0; t<j; ++t)
{
h=vis[p[t]-32];
if(!a[g].next[h])
{
a[k].init();
a[g].next[h]=k++;
}
g=a[g].next[h];
}
a[g].isword=1;
return ;
}
void acAutomation() //优化过的,可以当模板
{
int t, temp;
queue<int> q;
q.push(0);
while(!q.empty())
{
int s=q.front();
q.pop();
for(t=0; t<n; ++t)
{
if(a[s].next[t]==0)
{
if(s==0)a[s].next[t]=0;
else a[s].next[t]=a[a[s].fail].next[t]; //注意这里
}
else
{
temp=a[s].fail;
if(s==0)
{
a[a[s].next[t]].fail=0;
}
else
{
while(temp!=-1)
{
if(a[temp].next[t])
{
a[a[s].next[t]].fail=a[temp].next[t];
break;
}
temp=a[temp].fail;
}
if(temp==-1)
a[a[s].next[t]].fail=0;
}
a[a[s].next[t]].isword|=a[a[a[s].next[t]].fail].isword;
q.push(a[s].next[t]);
}
}
}
}
void add(int *a1, int *b1) //大数加法
{
int t, c=0;
for(t=0; t<100; ++t)
{
a1[t]=a1[t]+b1[t]+c;
c=a1[t]/10;
a1[t]%=10;
}
return ;
}
void solve()
{
int i, t, j, g;
memset(dp, 0, sizeof(dp));
dp[0][0][0]=1;
for(i=1; i<=m; ++i) //长度,类似矩阵一样(长度为m)就要m遍相加(矩阵就要m遍相乘)
{
for(j=0; j<k; ++j)
{
if(a[j].isword)
continue;
for(t=0; t<n; ++t)
{
g=a[j].next[t];
if(a[g].isword)
continue;
add(dp[i][g], dp[i-1][j]); //dp状态转移dp[i][g]+=dp[i-1][j]只不过这里要对大数处理,所以用第三维来储存大数的没一个数字
}
}
}
int ans[100];
memset(ans, 0, sizeof(ans));
for(t=0; t<k; ++t) //0包括哪些没有在字典树上的点(同样也有相同的长度m)的种类数
{
if(!a[t].isword)
add(ans, dp[m][t]);
}
for(t=99; t>=0; --t)
{
if(ans[t])break;
}
if(t<0)
printf("0\n");
else
{
while(t>=0)
{
printf("%d", ans[t]);
t--;
}
printf("\n");
}
return ;
}
int main()
{
int d, t, j, g;
char p[60];
while(scanf("%d%d%d", &n, &m, &d)!=EOF)
{
a[0].init();
k=1;
scanf("%s", p);
j=strlen(p);
for(t=g=0; t<j; ++t)
{
vis[p[t]-32]=g++; //vis表示不同字母的序号
}
for(t=0; t<d; ++t)
{
scanf("%s", p);
insert(p);
}
acAutomation();
solve();
}
return 0;
}
ac自动机(dp)<AC自动机模板> ---高精度处理
最新推荐文章于 2020-05-26 22:07:22 发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)