LA 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));
}
时间: 2024-11-05 15:00:20

LA 3942 Remember the Word(字典树+DP)的相关文章

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]匹配

UVA 3942 -- Remember the Word (字典树+dp)

Remember the Word Neal is very curious about combinatorial problems, and now here comes a problem about words. Knowing that Ray has a photographic memory and this may not trouble him, Neal gives it to Jiejie. Since Jiejie can't remember numbers clear

LA 3942 Remember the Word 字典树+dp

#include <cstdio> #include <cstring> using namespace std; #define mod 20071027 int dic[401000][28],val[401000]; char str[301000]; int dp[301000]; int s,sz; char T[110]; void insert(char *ch) { int u=0,len=strlen(ch); for(int i=0;i<len;i++)

LA 3942 Remember the Word (Trie)

Remember the Word 题目:链接 题意:给出一个有S个不同单词组成的字典和一个长字符串.把这个字符串分解成若干个单词的连接(单词可以重复使用),有多少种方法? 思路:令d[i]表示从字符i开始的字符串(后缀s[i..L])的分解数,这d[i] = sum{d(i+len(x)) | 单词x是其前缀}.然后将所有单词建成一个Trie树,就可以将搜索单词的复杂度降低. 代码: #include<map> #include<set> #include<queue>

2010辽宁省赛 NBUT 1222 English Game【字典树+DP】

[1222] English Game 时间限制: 1000 ms 内存限制: 131072 K 链接:Click Here! 问题描述 This English game is a simple English words connection game. The rules are as follows: there are N English words in a dictionary, and every word has its own weight v. There is a wei

zoj3013Word Segmenting (字典树+dp)

Word Segmenting Time Limit: 5 Seconds Memory Limit: 32768 KB Special Judge One key technology in Chinese search engine is Word Segmenting, which is more difficult than English Word Segmenting, as there is no space between words. A traditional solutio

LA ——3942 - Remember the Word(Trie 入门)

3942 - Remember the Word Regionals 2007 >> Asia - Nanjing Time limit: 3.000 seconds ------------------------------------------------------ 从右往左地推,令dp[i] 表示字符串  S[i....len]的分解方案数,则dp[i]=sum(dp[i+len(x)])  ,我们只要枚举 S[i....len]的前缀,在所给的单词中查找前缀,如果存在,则进行状态

LA 3942 - Remember the Word (字典树 + dp)

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1943 题目大意: 给定一个字符串和给定一个单词集合.问从给定单词集合中选取单词,有多少种选取方法刚好拼接成字符串. 例如: abcd 4 a b cd ab 有两种 a-b-cd ab-cd 这两种情况 解题思路: 因为给定的字符串的长度是3*10^5所以暴力就不能解决问题了

单词拆解&amp;前缀树&amp;树上DP LA 3942 Remember the Word

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=505&page=show_problem&problem=4147 3942 - Remember the Word Neal is very curious about combinatorial problems, and now here comes a problem about words. Knowing