[AC自动机+期望DP] 玲珑ACM 1025 - Magic boy Bi Luo with his excited string problem

来源:互联网 发布:大数据产业面临的问题 编辑:程序博客网 时间:2024/06/06 13:11

Magic boy Bi Luo with his excited string problem

题意:

给出<=15个字母串,每个串不超过10个字符,然后一个人开始写字母,每次随机写一个字母,直到出现给出的任意一个串,然后就停止,问写的长度的期望,答案mod 1e9+7。

思路:

总共150个字母比较少,用ac自动机建立转移矩阵,dp[i]表示从状态i出发写的期望,然后套高斯消元解方程。
每个状态可以写一个方程:

dp[i]=126dp[son[i][0]]+126dp[son[i][1]]++126dp[son[i][25]]+1

然后乘个26解决分数,移项过去就变成矩阵形式了。

////  main.cpp//  1025////  Created by 翅膀 on 16/9/16.//  Copyright © 2016年 kg20006. All rights reserved.//#include <iostream>#include <queue>#include <stdio.h>#include <algorithm>#include <math.h>#include <string.h>using namespace std;typedef long long ll;const ll mod = 1e9+7;const int N = 155;ll qpow(ll a, ll k) {    ll res = 1;    a = (a%mod+mod)%mod;    while(k) {        if(k&1) res = (res*a)%mod;        a = (a*a)%mod;        k >>= 1;    }    return res;}ll a[N][N];ll x[N];void swapcol(int x, int y, int row){    for(int i = 0; i < row; ++i){        swap(a[i][x], a[i][y]);    }}void getans(int row, int col){    for(int i = col-1; i >= 0; --i){        ll tmp = a[i][col];        for(int j = i+1; j < col; ++j){            tmp = ((tmp-a[i][j]*x[j]%mod)%mod+mod)%mod;        }        ll X = tmp*qpow(a[i][i], mod-2)%mod;        x[i] = X;    }}int Gauss(int row, int col){    int r = 0, c = 0;    for(; r < row && c < col; ++r, ++c){        int mx = r;        for(int i = r+1; i < row; ++i){            if(abs(a[i][c]) > abs(a[mx][c])) mx = i;        }        if(mx != r) swap(a[mx], a[r]);        if(a[r][c] == 0){ r--; continue; }        for(int i = r+1; i < row; ++i){            if(!a[i][c]) continue;            ll tmp1 = a[r][c], tmp2 = a[i][c];            for(int j = c; j <= col; ++j){                a[i][j] = (a[i][j]*tmp1 - a[r][j]*tmp2)%mod;                if(a[i][j] < 0) a[i][j] += mod;            }        }    }    for(int i = r; i < row; ++i){        if(a[i][col]) return -1;    }    int free_x = col-r; //自由元的个数    for(int i = 0, j; i < col && i < row; ++i){        if(!a[i][i]){            for(j = i+1; j < col; ++j) if(a[i][j]) break;            if(j < col) swapcol(i, j, row);        }    }    getans(row, col);    return free_x;}struct Trie{    static const int MX = 155;    int son[MX][26], fail[MX], end[MX];    int root, alloc;    int newnode(){        memset(son[++alloc], 0, sizeof(son[alloc]));        end[alloc] = 0, fail[alloc] = 0;        return alloc;    }    void init(){        alloc = 0;        root = newnode();    }    void insert(char *s) {        int p = root;        for(int i = 0; s[i]; ++i) {            if(son[p][s[i]-'a'] == 0) son[p][s[i]-'a'] = newnode();            p = son[p][s[i]-'a'];        }        end[p] = 1;    }    void build() {        queue<int>q;        for(int i = 0; i < 26; ++i) {            if(son[root][i] == 0) son[root][i] = root;            else fail[son[root][i]] = root, q.push(son[root][i]);        }        while(!q.empty()){            int u = q.front(); q.pop();            if(end[fail[u]]) end[u] = 1;            for(int i = 0; i < 26; ++i) {                if(son[u][i] == 0) son[u][i] = son[fail[u]][i];                else fail[son[u][i]] = son[fail[u]][i], q.push(son[u][i]);            }        }    }    ll DP(){        memset(a, 0, sizeof(a));        memset(x, 0, sizeof(x));        for(int i = 1; i <= alloc; ++i){            if(end[i]){                a[i-1][i-1] = 1;                a[i-1][alloc] = 0;                continue;            }            a[i-1][i-1] = 26;            for(int j = 0; j < 26; ++j) {                a[i-1][son[i][j]-1] -= 1;            }            a[i-1][alloc] = 26;        }        Gauss(alloc, alloc);        return x[0];    }}ac;char s[25];int main(int argc, const char * argv[]) {    int T, ca = 1;    scanf("%d", &T);    while(T--) {        ac.init();        int n;        scanf("%d", &n);        for(int i = 0; i < n; ++i) {            scanf("%s", s);            ac.insert(s);        }        ac.build();        printf("Case #%d: %lld\n", ca++, ac.DP());    }    return 0;}
0 0