题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1444

非权限题,就没粘贴题面了。

解法:

AC自动机+矩阵乘法

首先把模式串建成AC自动机,构建出转移矩阵。

构造方法:a[i][j]表示从第i个结点转移到第j个结点的概率,则如果j被标记过,f[i][j]=1,

否则f[i][j]=p[ch[j]]。

还有1个高斯消元的解法,纠结了好久,最后看discuss里面博主给了一个用期望高斯消元的博客,看懂了

https://blog.sengxian.com/solutions/bzoj-1444

///BZOJ 1444

#include <bits/stdc++.h>
using namespace std;
const int maxn = 510;
struct node{
    double p[maxn][maxn];
    node(){memset(p, 0, sizeof(p));}
}a;
char s[maxn];
int tree[maxn][26];
int fail[maxn];
bool word[maxn];
int n, l, m, cnt=1, id = 0;
double p[maxn];
int pos[maxn];

queue <int> q;

void ins()
{
    scanf("%s", s+1);
    int len = strlen(s+1), now=1;
    for(int i=1; i<=len; i++){
        int id=s[i]-'A';
        if(!tree[now][id]) tree[now][id]=++cnt;
        now=tree[now][id];
    }
    word[now]=1;
    pos[++id]=now;
}

void Get_fail()
{
    q.push(1);
    fail[1] = 0;
    while(!q.empty()){
        int u=q.front(); q.pop();
        word[u] |= word[fail[u]];
        for(int i=0; i<m; i++){
            int k = fail[u];
            while(k&&!tree[k][i]) k=fail[k];
            if(tree[u][i]){
                fail[tree[u][i]] = k?tree[k][i]:1;
                q.push(tree[u][i]);
            }
            else{
                tree[u][i]=k?tree[k][i]:1;
            }
        }
    }
}

void Get_maze(){
    for(int i=1; i<=cnt; i++){
        if(word[i]) a.p[i][i]=1;
        else for(int x=0; x<m; x++){
            a.p[i][tree[i][x]]+=p[x];
        }
    }
}

node operator * (const node &a, const node &b)
{
    node res;
    for(int i=1; i<=cnt; i++){
        for(int j=1; j<=cnt; j++){
            for(int k=1; k<=cnt; k++){
                res.p[i][j] += a.p[i][k]*a.p[k][j];
            }
        }
    }
    return res;
}

int main()
{
    scanf("%d%d%d", &n,&l,&m);
    for(int i=0; i<m; i++){
        double x, y;
        scanf("%lf%lf", &x,&y);
        p[i]=x/y;
    }
    for(int i=1; i<=n; i++){
        ins();
    }
    Get_fail();
    Get_maze();
    for(int i=1; i<=100; i++) a=a*a;
    for(int i=1; i<=n; i++) printf("%.2f\n", (double)a.p[1][pos[i]]);
    return 0;
}