• 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));
    }
  • 相关阅读:
    jQuery杂项方法
    nodeJS实现路由功能
    nodeJS之HTTP
    nodeJS之TCP模块net
    nodeJS之事件events
    NodeJS之queryString
    chrome谷歌浏览器用这种方式清除缓存比较方便了,必须是调试模式才行
    DeepMind已将AlphaGo引入多领域 Al泡沫严重
    学习Linux的正确姿势
    现在90,00后经常上哪些网站?喜欢看啥网站?
  • 原文地址:https://www.cnblogs.com/chuninsane/p/4923533.html
Copyright © 2020-2023  润新知