描述
随机吐出一个长为lenth的字符串,求E("最多包含多少个禁忌词")。E表示数学期望。
思路
AC自动机+DP+矩阵乘法。。。
代码
注意:prG函数用来debug用的,请无视。
注意看输入格式。
注意AC自动机的计算时的关系。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define NMAX 101
int alpha,num;
struct node
{
int name;
bool end;
node *next[26],*fa,*fail;
node(){end=0;fail=NULL;memset(next,0,sizeof(next));}
}epool[NMAX],*etop,*head;
void init()
{
etop=epool;
head=etop++;
}
void add(char *c)
{
node *p=head;
for (int i=0;i<strlen(c);i++)
{
int x=c[i]-'a';
if (!p->next[x])
{
etop->fa=p;
etop->name=x;
p->next[x]=etop++;
}
p=p->next[x];
}
p->end=1;
}
node *Q[NMAX];
void build_ac()
{
int top,bot;
top=bot=0;
Q[bot++]=head;
node *t,*p;
while(top<bot)
{
t=Q[top++];
if (t->fa==head) t->fail=head;
else if (t!=head)
{
int x=t->name;
p=t->fa->fail;
t->fail=p->next[x];
t->end|=p->next[x]->end;
}
for (int i=0;i<alpha;i++)
{
if (t->next[i]) Q[bot++]=t->next[i];
else
{
if (t==head) t->next[i]=head;
else t->next[i]=t->fail->next[i];
}
}
}
}
struct matrix
{
long double a[NMAX][NMAX];
matrix(){memset(a,0,sizeof(a));}
};
matrix operator * (const matrix &x,const matrix &y)
{
matrix ret;
for (int i=0;i<num;i++)
for (int j=0;j<num;j++)
for (int k=0;k<num;k++)
ret.a[i][j]+=x.a[i][k]*y.a[k][j];
return ret;
}
double pow(matrix g,int n)
{
matrix ret;
for (int i=0;i<num;i++) ret.a[i][i]=1;
while (n)
{
if (n&1) ret=ret*g;
g=g*g;
n>>=1;
}
return ret.a[0][num-1];
}
matrix G;
void buildG()
{
node *t;
num=etop-epool+1;
for (int i=0;i<num-1;i++)
{
for (int j=0;j<alpha;j++)
{
t=epool+i;
int jaddr=t->next[j]-epool;
if (t->next[j]->end)
{
G.a[i][0]+=1./alpha;G.a[i][num-1]+=1./alpha;
}
else
G.a[i][jaddr]+=1./alpha;
}
}
G.a[num-1][num-1]=1;
}
void prG()
{
printf("NUM=%d\n",num);
for (int i=0;i<num;i++)
{
for (int j=0;j<num;j++)
printf("%.3f ",G.a[i][j]);
printf("\n");
}
}
int main()
{
init();
char tmp[20];
int n,lenth;
scanf("%d%d%d",&n,&lenth,&alpha);
for (int i=0;i<n;i++)
scanf("%s",tmp),add(tmp);
build_ac();
buildG();
//prG();
/*for (int i=0;i<num-1;i++)
{
printf("%d :",i);
for (int j=0;j<alpha;j++)
{
if (epool[i].next[j])
printf("%d",epool[i].next[j]-epool);
}
printf("\n");
}*/
printf("%f\n",pow(G,lenth));
return 0;
}