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

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1943

    题意:一个长字符串和多个短字符串,求短字符串有多少种方式组成长字符串。

    状态转移方程: dp[i] = sum(d[i + len(x)])  (x是s[i...L]的前缀) 

    对于每个i,如果直接暴力寻找s[i...L]的前缀,复杂度为O(nm) (n为短字符串的个数,m为短字符串的长度),肯定会超时。

    既然是求前缀,那么可以使用前缀树(字典树)来解决此问题。用字典树寻找前缀的复杂度为O(m)。

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #define maxn 400100
    #define maxm 300010
    #define mod 20071027
    #define sigma_size 26
    using namespace std;
    
    char str[maxm], tstr[110];
    int dp[maxm], ch[maxn][sigma_size], val[maxn], sz;
    
    struct Trie
    {
        int get_id(char c)
        {
            return c - 'a';
        }
        
        void insert(char* str, int v)
        {
            int u = 0, len = (int)strlen(str);
            for (int i = 0; i < len; ++i)
            {
                int id = get_id(str[i]);
                if (!ch[u][id])
                {
                    memset( ch[sz], 0, sizeof(ch[sz]));
                    val[sz] = 0;
                    ch[u][id] = sz++;
                }
                u = ch[u][id];
            }
            val[u] = v;
        }
        
        int query(char* str, int start)
        {
            int u = 0, result = 0, len = (int)strlen(str), next;
            for (int i = 0; i < len; ++i)
            {
                int id = get_id(str[i]);
                next = ch[u][id];
                if (next)
                {
                    if (val[next])
                        result = (result + dp[i + start + 1])%mod;
                }
                else
                    break;
                u = next;
            }
            return result;
        }
    };
    
    void init();
    
    int main(void)
    {
        int ca = 1, n;
        while (scanf("%s", str) != EOF)
        {
            init();
            int len = (int)strlen(str);
            
            scanf("%d", &n);
            Trie trie = Trie();
            while (n--)
            {
                scanf("%s", tstr);
                trie.insert( tstr, 1);
            }
            
            dp[len] = 1;
            for (int i = len - 1; i >= 0; i--)
            {
                dp[i] = trie.query( str + i, i);
            }
            printf("Case %d: %d\n", ca++, dp[0]);
        }
        return 0;
    }
    
    void init()
    {
        sz = 1;
        memset( dp, 0, sizeof(dp));
        memset( ch[0], 0, sizeof(ch[0]));
        memset( val, 0, sizeof(val));
    }
  • 相关阅读:
    算法分析设计实践——相容问题
    算法分析设计实践——最长公共子序列
    算法分析设计实践——矩阵链乘法
    Rotate Columns (easy version) CodeForces
    Save the Nature CodeForces
    Similar Arrays CodeForces
    算法分析设计实践——投资问题
    皇后问题(BFS解法)
    Git的基本使用
    在阿里云服务器上部署ssm项目
  • 原文地址:https://www.cnblogs.com/chuninsane/p/4923533.html
Copyright © 2011-2022 走看看