• 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;
    }
  • 相关阅读:
    面向对象程序设计寒假作业2
    终于开通了园子里的贴号
    java中与类继承相关的知识点
    动态代理机制之查看一个类或接口中有哪些方法
    动态代理
    xml与html的区别
    深入理解linux i节点(inode)
    netstat命令
    关于C++ const 的全面总结
    linux 下 进程和线程的区别
  • 原文地址:https://www.cnblogs.com/xiaochaoqun/p/7270221.html
Copyright © 2020-2023  润新知