UVA 11468 Substring(AC自动机+dp)

来源:互联网 发布:淘宝牙齿矫正器 编辑:程序博客网 时间:2024/04/28 12:28

题意就是给你几个模板串,以及一些字符的出现概率,随机选择字符L次后得到一个长度为L的字符串,问这个字符串不包括任何一个模板串的概率。

比较简单的题,把模板串构建成AC自动机,随机选择字符相当于在字典树里走一步,如果是单词节点处那么就不能走,或者走到没有点的位置,由于构造的是改造过的AC自动机所以直接由失配指针走到他下一个可能匹配的地方继续走。dp[i][j]代表还有i步要走,进入j节点的概率,记忆化搜索即可

AC代码:

//#pragma comment(linker, "/STACK:102400000,102400000")#include<cstdio>#include<ctype.h>#include<algorithm>#include<iostream>#include<cstring>#include<vector>#include<cstdlib>#include<stack>#include<cmath>#include<queue>#include<set>#include<map>#include<ctime>#include<string.h>#include<string>#include<sstream>#include<bitset>using namespace std;#define ll __int64#define ull unsigned long long#define eps 1e-8#define NMAX 1000000005#define MOD 1000000007#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1#define PI acos(-1)template<class T>inline void scan_d(T &ret){    char c;    int flag = 0;    ret=0;    while(((c=getchar())<'0'||c>'9')&&c!='-');    if(c == '-')    {        flag = 1;        c = getchar();    }    while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();    if(flag) ret = -ret;}double p[62];const int SIGMA_SIZE = 62;struct AhoCorasick{    int ch[20*25][SIGMA_SIZE];    int match[20*25],f[20*25],vis[105][20*25];    double dp[105][20*25];    int sz;    void init()    {        sz = 1; memset(ch[0],0,sizeof(ch[0]));        memset(match,0,sizeof(match));        memset(vis,0,sizeof(vis));    }    int idx(char c)    {        if(islower(c)) return c-'a';        else if(isupper(c)) return c-'A'+26;        else return c-'0'+52;    }    void insert(char *s)    {        int u = 0, n = strlen(s);        for(int i = 0; i < n; i++)        {            int c = idx(s[i]);            if(!ch[u][c])            {                memset(ch[sz],0,sizeof(ch[sz]));                match[sz] = 0;                ch[u][c] = sz++;            }            u = ch[u][c];        }        match[u] = 1;    }    void getfail()    {        queue<int>q;        f[0] = 0;        for(int c = 0; c < SIGMA_SIZE; c++)        {            int u = ch[0][c];            if(u){f[u] = 0; q.push(u); }        }        while(!q.empty())        {            int r = q.front(); q.pop();            for(int c = 0; c < SIGMA_SIZE; c++)            {                int u = ch[r][c];                if(!u)                {                    ch[r][c] = ch[f[r]][c];                    continue;                }                q.push(u);                int v = f[r];                while(v && !ch[v][c]) v = f[v];                f[u] = ch[v][c];                match[u] |= match[f[u]];            }        }    }    double dfs(int dep,int pos)    {        if(dep == 0) return 1.0;        if(vis[dep][pos]) return dp[dep][pos];        vis[dep][pos] = 1;        double &ans = dp[dep][pos];        ans = 0;        for(int i = 0; i < SIGMA_SIZE; i++) if(p[i] != 0.0)        {            int u = ch[pos][i];            if(!match[u]) ans += p[i]*dfs(dep-1,u);        }        return ans;    }};AhoCorasick ac;int main(){#ifdef GLQ    freopen("input.txt","r",stdin);//    freopen("o1.txt","w",stdout);#endif // GLQ    int t,k,n,l,cas = 1;    scanf("%d",&t);    while(t--)    {        ac.init();        scanf("%d",&k);        char tmp[25];        for(int i = 0; i < k; i++)        {            scanf("%s",tmp);            ac.insert(tmp);        }        scanf("%d\n",&n);        memset(p,0,sizeof(p));        for(int i = 0; i < n; i++)        {            char tp;            double ha;            scanf("%c %lf\n",&tp,&ha);            p[ac.idx(tp)] = ha;        }        ac.getfail();        scanf("%d",&l);        printf("Case #%d: %.6lf\n",cas++,ac.dfs(l,0));    }    return 0;}


0 0