题目大意:给定n个模式串,定义一个字符串的伤害为所有子串的划分中最多包含的模式串数量,求长度为len的字符串的伤害期望值
小五prpr,恋恋prpr,二小姐prpr
首先建立AC自动机 令f[i][j]表示长度为i的字符串在AC自动机上的第j个节点的伤害期望值
如果要走到某个节点是危险节点或者fail指针指向危险节点,就ans++,然后回到根节点
这样构造出来的矩阵做快速幂= = 这么做都会把- - 不会别骂我- -
但是跑完发现找不到答案- - 因此我们需要稍微改造一下- -
新建一个节点 如果某个节点因为危险返回了根 就同时向该节点连一条边
新节点的唯一一条出边边权为1指向自己- - 这样搞出来的邻接矩阵自乘len次,得到的矩阵的[root][new_node]就是答案- -
相当于把AC自动机看成一个图 去图上求根到新节点走恰好len步的期望值
好题- - 注意开long double不然卡精- - 虽说如此总比那些用double去卡long double精度的题强- -
大半夜的我写的是啥自己都看不懂了- - 没看懂的地方去看代码吧但愿写的还能清晰点。。。 吧。。。
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define M 110
using namespace std;
int n,len,alphabet;
char s[M];
namespace Aho_Corasick_Automaton{
struct Trie{
Trie *son[26],*fail;
bool ed;
}mempool[M],*C=mempool,*root;
void Insert(Trie* &p,char *s)
{
if(!p) p=C++;
if(!*s)
{
p->ed=1;
return ;
}
Insert(p->son[(*s)-'a'],s+1);
}
void Build_Tree()
{
static Trie *q[M];
int i,r=0,h=0;
for(i=0;i<26;i++)
if(root->son[i])
(q[++r]=root->son[i])->fail=root;
else
root->son[i]=root;
while(r!=h)
{
Trie *p=q[++h];
for(i=0;i<26;i++)
if(p->son[i])
{
p->son[i]->fail=p->fail->son[i];
p->son[i]->ed|=p->fail->son[i]->ed;
q[++r]=p->son[i];
}
else
p->son[i]=p->fail->son[i];
}
}
}
namespace Matrix_Multiplication{
int size;
struct Matrix{
long double memory[M][M];
Matrix()
{
memset(memory,0,sizeof memory);
}
long double* operator [] (int x)
{
return memory[x];
}
friend void operator *= (Matrix &x,Matrix &y)
{
int i,j,k;
Matrix z;
for(i=0;i<=size;i++)
for(j=0;j<=size;j++)
for(k=0;k<=size;k++)
z[i][j]+=x[i][k]*y[k][j];
x=z;
}
}f;
Matrix Quick_Power(Matrix x,int y)
{
Matrix re;
for(int i=0;i<=size;i++)
re[i][i]=1;
while(y)
{
if(y&1) re*=x;
x*=x;y>>=1;
}
return re;
}
}
int main()
{
using namespace Aho_Corasick_Automaton;
using namespace Matrix_Multiplication;
int i,j;
cin>>n>>len>>alphabet;
for(i=1;i<=n;i++)
{
scanf("%s",s+1);
Insert(root,s+1);
}
Build_Tree();
size=C-mempool;
long double temp=1.0/alphabet;
for(j=0;j<size;j++)
{
for(i=0;i<alphabet;i++)
{
int k;
if(mempool[j].son[i]->ed)
{
f[j][0]+=temp;
f[j][size]+=temp;
}
else
f[j][mempool[j].son[i]-mempool]+=temp;
}
}
f[size][size]=1;
Matrix ans=Quick_Power(f,len);
cout<<fixed<<setprecision(10)<<ans[0][size];
return 0;
}