UVA-1401-Remember the Word(Trie)

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 clearly, he just uses sticks to help himself. Allowing for Jiejie‘s only 20071027 sticks, he can only record the remainders of the numbers divided by total amount of sticks.

The problem is as follows: a word needs to be divided into small pieces in such a way that each piece is from some given set of words. Given a word and the set of words, Jiejie should calculate the number of ways the
given word can be divided, using the words in the set.

Input

The input file contains multiple test cases. For each test case: the first line contains the given word whose length is no more than 300 000.

The second line contains an integer S , 1S4000 .

Each of the following S lines contains one word from the set. Each word will be at most 100 characters long. There will be no two identical words and all letters in the words will
be lowercase.

There is a blank line between consecutive test cases.

You should proceed to the end of file.

Output

For each test case, output the number, as described above, from the task description modulo 20071027.

Sample Input

abcd
4
a
b
cd
ab

Sample Output

Case 1: 2

思路:dp[i]表示从第i个字符开始到字符串尾的组合情况的方案数,从后往前推即可。

#include <stdio.h>
#include <string.h>

int son[400001][26],val[400001],dp[400001],cnt;

char s[300001],ts[101];

void insert(char *str)
{
    int u=0,i,j,id;

    for(i=0;str[i];i++)
    {
        id=str[i]-‘a‘;

        if(!son[u][id])
        {
            for(j=0;j<26;j++) son[cnt][j]=0;

            val[cnt]=0;

            son[u][id]=cnt++;
        }

        u=son[u][id];
    }

    val[u]++;
}

int main()
{
    int n,i,j,u,id,casenum=1;

    while(~scanf("%s",s))
    {
        for(i=0;i<26;i++) son[0][i]=0;
        cnt=1;

        scanf("%d",&n);

        while(n--)
        {
            scanf("%s",ts);

            insert(ts);
        }

        n=strlen(s);

        dp[n]=1;

        for(i=n-1;i>=0;i--)
        {
            u=0;
            j=i;
            id=s[j]-‘a‘;

            dp[i]=0;

            while(u=son[u][id])//如果可以继续走下去就继续走
            {
                dp[i]+=val[u]%20071027*dp[j+1]%20071027;

                j++;

                if(j<n) id=s[j]-‘a‘;
                else break;
            }
        }

        printf("Case %d: %d\n",casenum++,dp[0]%20071027);
    }

}

UVA-1401-Remember the Word(Trie)

时间: 2024-11-01 03:31:32

UVA-1401-Remember the Word(Trie)的相关文章

uva 1401 Remember the Word ( Trie + DP )

题意:给出n(n<=4000)个单词和一个字符串(len<=300000),求把这个字符串分解成若干个单词的拼接,有多少种方法 思路:Trie,先把单词建成Trie,然后进行dp,dp[i]表示以字符串中第i个字母为开头的情况,然后每个状态只要在Trie树上找到相应的字母开头的单词,然后dp[i] = sum{dp[i + len(x)]}进行状态转移即可 这个x是n个单词中的一个,可以用Trie查询 code: #include<cstdio> #include<cstri

LA 3942 &amp;&amp; UVa 1401 Remember the Word (Trie + DP)

题意:给你一个由s个不同单词组成的字典和一个长字符串L,让你把这个长字符串分解成若干个单词连接(单词是可以重复使用的),求有多少种.(算法入门训练指南-P209) 析:我个去,一看这不是一个DP吗?刚开始交一直是runtime error,找了好久,一直以为是数组开小了,不断增大还是这样,后来发现我用了char类型...下面分析这个题目 应该不难想到这个状态转移方程: d(i) = sum{d(i+len(x))|单词x是s[i...L]的前缀},其中len(x)是长度.d(i)表示从字符i开始

UVa 1401 Remember the Word

Trie+DP 大白书上的字典树训练题. 题意是说一个字符串可能有多少种小串组成. 例如 abcd 4 a b cd ab abcd=a+b+cd:abcd=ab+cd: 递推为:从最后一位往前,dp[i]=dp[i]+dp[i+ len[x]]  x为输入时的顺序,附加到节点中.是 i~strlen(S)的前缀.S[1,2,3,-,i,-len] 构建Trie树时,把顺序也附加到节点中. 最后search的时候 找出为多少个字符串的前缀,并把这些前缀都加起来. #include<cstdio>

UVA - 1401 Remember the Word(trie+dp)

1.给一个串,在给一个单词集合,求用这个单词集合组成串,共有多少种组法. 例如:串 abcd, 单词集合 a, b, cd, ab 组合方式:2种: a,b,cd ab,cd 2.把单词集合建立字典树,然后从后向前dp,dp[i]=dp[i]+dp[i+len(x)]; 其中x为当前找到的前缀长度. 3. #include<iostream> #include<stdio.h> #include<string.h> using namespace std; #defin

uva 1401 dp+Trie

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=&problem=4147 题意:给定一个字符串,以及若干单词,求有几种方式能用单词组成字符串 我先是dp方程推得有问题不知怎么修改搞得卡了很久,然后就是数组开得太小一直RE trie数组大小=单词个数*单词长度  dp[i]为以str[i]开头的后缀的ans,dp[i]=segma(

UVA 3942 - Remember the Word (Trie)

3942 - 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 number

uva 1401

Neal is very curious about combinatorial problems, and now here comes a problem about words. Knowingthat Ray has a photographic memory and this may not trouble him, Neal gives it to Jiejie.Since Jiejie can't remember numbers clearly, he just uses sti

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>

UVa 1401 (Tire树) Remember the Word

d(i)表示从i开始的后缀即S[i, L-1]的分解方法数,字符串为S[0, L-1] 则有d(i) = sum{ d(i+len(x)) | 单词x是S[i, L-1]的前缀 } 递推边界为d(L) = 1,代表空串. 将前n个单词构造一颗Tire树,在树中查找后缀的过程中遇到一个单词节点就代表找到一个状态转移中的x 1 #include <cstdio> 2 #include <cstring> 3 4 const int maxnode = 400000 + 10; 5 co