zoukankan      html  css  js  c++  java
  • UVALive 3942 Remember the Word 字典树+dp

    /**
    题目:UVALive 3942 Remember the Word 
    链接:https://vjudge.net/problem/UVALive-3942
    题意:给定一个字符串(长度最多3e5)和m个单词(每个单词长度最多100)。单词都是不同的。该字符串可以由若干个单词组成,问最多有多少种组合方式。
    
    思路:字典树+dp
    用字典树处理好m个单词,定义dp[i]表示从i开始的字符串可以由单词组成的方式数。
    那么dp[i] += dp[i+j]; j表示某个单词和字符串的[i,i+j-1]匹配。
    
    */
    
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<map>
    #include<vector>
    #include<queue>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef pair<int,int> P;
    typedef long long LL;
    const int mod = 20071027;
    const int INF = 0x3f3f3f3f;
    const int maxnode = 4e5+10;///最多可能有多少个节点
    const int maxn = 3e5+100;
    const int sigma_size = 26;///26个字母
    int dp[maxn];
    char s[maxn], ss[maxn];安全1
    int ch[maxnode][sigma_size];///由于很大,所以结构体内部放不下。要放在外面。
    struct Trie{
        int val[maxnode];
        int sz;
        int idx(char c){return c-'a';}
    
        void insert(char *s,int v)
        {
            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]);
                    val[sz] = 0;
                    ch[u][c] = sz++;
                }
                u = ch[u][c];
            }
            val[u] = v;
        }
    
        void query(int sta,int off)
        {
            int u = 0;
            int c = idx(s[sta]);
            while(s[sta]!=''&&ch[u][c]){
                if(val[ch[u][c]]){
                    dp[sta-off] = (dp[sta-off]+dp[sta+1])%mod;
                }
                u = ch[u][c];
                c = idx(s[++sta]);
                off++;
            }
        }
    };
    
    int main()
    {
        int cas = 1;
        int n;
        Trie trie;
        while(scanf("%s",s)==1)
        {
            scanf("%d",&n);
            trie.sz = 1;
            memset(ch[0], 0, sizeof ch[0]);
            for(int i = 0; i < n; i++){
                scanf("%s",ss);
                trie.insert(ss,1);
            }
            int m = strlen(s);
            memset(dp, 0, sizeof dp);
            dp[m] = 1;
            for(int i = m-1; i>=0; i--){
                trie.query(i,0);
            }
            printf("Case %d: %d
    ",cas++,dp[0]);
        }
        return 0;
    }
  • 相关阅读:
    Hlg 1740 DP求路径且按最小字典序输出.cpp
    Uestc 1720 【容斥原理】.cpp
    Uva 10112 【简单的计算几何】.cpp
    Vijos 1071 【DP之记录路径】
    Hlg 1665 【KMP】.cpp
    cf 226b 唯美思维题~.cpp
    Hlg 1049 【广搜+康拓展开】.cpp
    Hlg 1067 【状态压缩DP】.cpp
    Pythoner.CN: 中小企业IT不可错过的十大虚拟机软件 | Pythoner.CN
    OpenStack Hacker养成指南 | UnitedStack Inc.
  • 原文地址:https://www.cnblogs.com/xiaochaoqun/p/7270221.html
Copyright © 2011-2022 走看看