zoukankan      html  css  js  c++  java
  • UVA 11468 Substring AC自动机+概率dp

    设dp[u][L]为当前在结点u,再走L步合法的概率。

    如果当前结点不是单词结点,并不能判定该结点一定合法,还应该沿着失配边往回走,因为可能失配边往回走的过程中出现了不合法的,不过这里不需要专门往回走,只要看last就可以知道往回走的过程中是否有单词结点了。

    都发现了这一点了,居然还是WA了。。。本来判定就慢。。。还坑多。。。万恶的uva。。。。

    先留代码,明天再调。。。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define  MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=100100;
    const int INF=1e9+10;
    
    int K,N,L;
    double pro[maxn];
    double dp[510][120];
    bool  vis[510][120];
    char s[1200][1200];
    const int cn=10+26+26;
    int idx[maxn];
    
    struct Trie
    {
        int ch[maxn][cn];
        int End[maxn];
        int f[maxn];
        int last[maxn];
        int rt,tot;
        int newnode()
        {
            ++tot;
            memset(ch[tot],-1,sizeof(ch[tot]));
            End[tot]=0;
            return tot;
        }
        void init()
        {
            tot=-1;
            rt=newnode();
        }
        void insert(char *s)
        {
            int len=strlen(s);
            int u=rt;
            REP(i,0,len-1){
                int c=idx[s[i]];
                if(ch[u][c]==-1) ch[u][c]=newnode();
                u=ch[u][c];
            }
            End[u]++;
        }
        void build()
        {
            queue<int> q;
            f[rt]=rt;last[rt]=rt;
            REP(c,0,N-1){
                if(~ch[rt][c]) f[ch[rt][c]]=rt,q.push(ch[rt][c]);
                else ch[rt][c]=rt;
            }
            while(!q.empty()){
                int u=q.front();q.pop();
                REP(c,0,N-1){
                    if(~ch[u][c]) f[ch[u][c]]=ch[f[u]][c],q.push(ch[u][c]);
                    else ch[u][c]=ch[f[u]][c];
                    if(End[f[u]]) last[u]=f[u];
                    else last[u]=last[f[u]];
                }
            }
        }
        double dfs(int u,int L)
        {
            if(vis[u][L]) return dp[u][L];
            vis[u][L]=1;
            double &res=dp[u][L];
            if(End[u]||last[u]) return res=0;
            if(L==0) return res=1;
            res=0;
            REP(c,0,N-1){
                int v=ch[u][c];
                res+=pro[c]*dfs(v,L-1);
            }
            return res;
        }
    };Trie ac;
    
    int main()
    {
        freopen("in.txt","r",stdin);
        int T;cin>>T;
        REP(casen,1,T){
            scanf("%d",&K);
            REP(i,1,K){
                scanf("%s",s[i]);
            }
            scanf("%d",&N);
            double p;char c;
            REP(i,0,N-1){
                cin>>c>>p;
                idx[c]=i;
                pro[i]=p;
            }
            ac.init();
            REP(i,1,K) ac.insert(s[i]);
            ac.build();
            scanf("%d",&L);
            MS0(vis);
            printf("Case #%d: %.6f
    ",casen,ac.dfs(ac.rt,L));
        }
        return 0;
    }
    /**
    2
    1
    a
    2
    a 0.5
    b 0.5
    2
    2
    ab
    ab
    2
    a 0.2
    b 0.8
    2
    */
    View Code

    -------------- 

    是我英语不好还是题目真坑。。。刚想关电脑睡觉,睡前把刚才第一次写的代码改了一下提交,居然过了。。。。一开始我没看到题目的“Valid characters are all alphanumeric characters”这句话,于是建立初始化字典树的时候把cn设为64(最多的情况10+26+26),但是题目明明说了“Valid characters are all alphanumeric characters”给定的字符包括所有模版串用到的字符?。。。于是我只把cn开成了N。。。

    本来就没必要改。。。按原来那样写常数大了一点,但复杂度明显不会超,牺牲一些运行效率却能大大增加代码准确性,而且可以避开题目潜在的坑。。。和数组开大点是一个道理。。

    不过重点还是前面的失配边。。。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define  MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=100100;
    const int INF=1e9+10;
    
    int K,N,L;
    double pro[maxn];
    double dp[510][120];
    bool  vis[510][120];
    char s[maxn];
    const int cn=10+26+26;
    
    int idx(char c)
    {
        if(isdigit(c)) return c-'0';
        else if(isupper(c)) return 10+c-'A';
        else return 10+26+c-'a';
    }
    
    struct Trie
    {
        int ch[maxn][cn];
        int End[maxn];
        int f[maxn];
        int last[maxn];
        int rt,tot;
        int newnode()
        {
            ++tot;
            memset(ch[tot],-1,sizeof(ch[tot]));
            End[tot]=0;
            return tot;
        }
        void init()
        {
            tot=-1;
            rt=newnode();
        }
        void insert(char *s)
        {
            int len=strlen(s);
            int u=rt;
            REP(i,0,len-1){
                int c=idx(s[i]);
                if(ch[u][c]==-1) ch[u][c]=newnode();
                u=ch[u][c];
            }
            End[u]++;
        }
        void build()
        {
            queue<int> q;
            f[rt]=rt;last[rt]=rt;
            REP(c,0,cn-1){
                if(~ch[rt][c]) f[ch[rt][c]]=rt,q.push(ch[rt][c]);
                else ch[rt][c]=rt;
            }
            while(!q.empty()){
                int u=q.front();q.pop();
                REP(c,0,cn-1){
                    if(~ch[u][c]) f[ch[u][c]]=ch[f[u]][c],q.push(ch[u][c]);
                    else ch[u][c]=ch[f[u]][c];
                    if(End[f[u]]) last[u]=f[u];
                    else last[u]=last[f[u]];
                }
            }
        }
        double dfs(int u,int L)
        {
            if(vis[u][L]) return dp[u][L];
            vis[u][L]=1;
            double &res=dp[u][L];
            if(End[u]||last[u]) return res=0;
            if(L==0) return res=1;
            res=0;
            REP(c,0,cn-1){
                int v=ch[u][c];
                res+=pro[c]*dfs(v,L-1);
            }
            return res;
        }
    };Trie ac;
    
    int main()
    {
        freopen("in.txt","r",stdin);
        int T;cin>>T;
        REP(casen,1,T){
            scanf("%d",&K);
            ac.init();
            REP(i,1,K){
                scanf("%s",s);
                ac.insert(s);
            }
            ac.build();
            scanf("%d",&N);
            REP(i,0,cn-1) pro[i]=0;
            double p;char c;
            REP(i,1,N){
                cin>>c>>p;
                pro[idx(c)]=p;
            }
            scanf("%d",&L);
            MS0(vis);
            printf("Case #%d: %.6f
    ",casen,ac.dfs(ac.rt,L));
        }
        return 0;
    }
    /**
    2
    1
    a
    2
    a 0.5
    b 0.5
    2
    2
    ab
    ab
    2
    a 0.2
    b 0.8
    2
    */
    View Code
    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    Atitit  atiMail atiDns新特性 v2  q39
    Atitit  atiMail atiDns新特性 v2  q39
    Atitit.aticmd v4  新特性q39 添加定时器释放功能
    Atitit.aticmd v4  新特性q39 添加定时器释放功能
    Atitit. Atiposter 发帖机 新特性 poster new feature   v7 q39
    Atitit. Atiposter 发帖机 新特性 poster new feature   v7 q39
    Atitit.编程语言and 自然语言的比较and 编程语言未来的发展
    Atitit.编程语言and 自然语言的比较and 编程语言未来的发展
    atitit.解决struts2 SpringObjectFactory.getClassInstance NullPointerException  v2 q31
    知也atitit.解决struts2 SpringObjectFactory.getClassInstance NullPointerException  v2 q31无涯 - I
  • 原文地址:https://www.cnblogs.com/--560/p/5260312.html
Copyright © 2011-2022 走看看