题目链接:[BeiJing2011]禁忌
刚刚写了两道AC自动机+DP的傻X题以为自己很NB,然后信心满满的找到了这道题,然后就被艹翻了QAQ
题意都是看着po姐的博客才明白的,语死早……
就是求长度为len的所有串的最大伤害的期望值(平均值)
首先走到每个串都是有一定概率的,走到禁忌串也是,我们令dp[i][j]表示从i节点走到j节点的概率,那么答案就是走到所有禁忌串的概率
发现这样并没有办法统计答案,因此要加一个新点表示所有的禁忌串
然后所有禁忌串向这个点连边,表示走到了禁忌串
同时所有禁忌串向根节点0连边,表示走到禁忌串后返回,因为我们是把串分隔开来统计禁忌串的数目的,所以要回到根节点
那么现在这个图就和普通的邻接矩阵的图十分相似,我们把它len次方后dp[0][新点]就是走到禁忌串的概率和
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define LL long long
#define ld long double
using namespace std;
const int maxn=110;
const int mod=100000;
int n,m,alphabet,L;
char str[maxn];
struct AC_automation{
int next[maxn][26];
int end[maxn],fail[maxn];
int l,root;
ld dp[80][80],b[80][80];
int newnode(){
for (int i=0;i<26;++i) next[l][i]=-1;
end[l]=fail[l]=0; return l++;
}
void init(){
l=0; root=newnode();
}
int idx(char c){
return c-'a';
}
void ins(char buf[]){
int now=root,len=strlen(buf);
for (int i=0;i<len;++i){
int x=idx(buf[i]);
if (next[now][x]==-1)
next[now][x]=newnode();
now=next[now][x];
}end[now]=1;
}
void build(){
queue<int>q; fail[root]=root;
for (int i=0;i<26;++i)
if (next[root][i]!=-1){
q.push(next[root][i]);
fail[next[root][i]]=root;
}else next[root][i]=root;
while (!q.empty()){
int now=q.front(); q.pop();
for (int i=0;i<26;++i)
if (next[now][i]!=-1){
q.push(next[now][i]);
fail[next[now][i]]=next[fail[now]][i];
if (end[fail[next[now][i]]]) end[next[now][i]]=1;
}else next[now][i]=next[fail[now]][i];
}
}
void Init_Matrix(){
ld addans=1.0/alphabet;
for (int i=0;i<l;++i)
for (int j=0;j<alphabet;++j)
if (end[next[i][j]]){
dp[i][0]+=addans;
dp[i][l]+=addans;
}else dp[i][next[i][j]]+=addans;
dp[l][l]=1; b[0][0]=0;
for (int i=0;i<=l;++i)
for (int j=0;j<=l;++j)
b[i][j]=i==j;
}
void mul(ld a[80][80],ld b[80][80],ld c[80][80]){
ld tmp[80][80];
for (int i=0;i<=l;++i)
for (int j=0;j<=l;++j){
tmp[i][j]=0;
for (int k=0;k<=l;++k)
tmp[i][j]+=a[i][k]*b[k][j];
}
for (int i=0;i<=l;++i)
for (int j=0;j<=l;++j)
c[i][j]=tmp[i][j];
}
void Matrix_power(){
while (L){
if (L&1) mul(b,dp,b);
mul(dp,dp,dp); L>>=1;
}cout<<fixed<<setprecision(15)<<b[0][l];
}
}Ac;
int main(){
Ac.init();
scanf("%d%d%d",&n,&L,&alphabet);
for (int i=1;i<=n;++i){
scanf("%s",str);
Ac.ins(str);
}
Ac.build();
Ac.Init_Matrix();
Ac.Matrix_power();
}