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;

#define MAX 26
#define MOD 20071027

int dp[300005];

struct Trie
{
    Trie *next[MAX];
    int v;   //根据需要变化,1代表无此单词,-1代表有此单词
};
Trie *root;

void createTrie(char *str)
{
    int len = strlen(str);
    Trie *p = root, *q;
    for(int i=0; i<len; ++i)
    {
        int id = str[i]-‘a‘;
        if(p->next[id] == NULL)
        {
            // q = (Trie *)malloc(sizeof(Trie));
            q = new Trie;
            q->v = 1;    //初始v==1
            for(int j=0; j<MAX; ++j)
                q->next[j] = NULL;
            p->next[id] = q;
        }
        p = p->next[id];
    }
    p->v = -1;   //若为结尾,则将v改成-1表示
}
int findTrie(char *str,int mI,int len)
{
    int ret=0;
    //int len = strlen(str);//每次都计算,很浪费时间
    Trie *p = root;
    for(int i=mI; i<len; ++i)
    {
        int id = str[i]-‘a‘;
        p = p->next[id];
        if(p == NULL)   //若为空集,表示不存以此为前缀的串
            return ret;
        if(p->v == -1){   //字符集中已有串是此串的前缀
            ret=(ret+dp[i+1])%MOD;
        }
    }
    return ret;
}
int deleteTrie(Trie* T)
{
    int i;
    if(T==NULL)
        return 0;
    for(i=0; i<MAX; i++)
    {
        if(T->next[i]!=NULL)
            deleteTrie(T->next[i]);
    }
    //free(T);
    delete(T);
    return 0;
}
int main()
{
    char str[300005];
    char str2[105];
    int i,S,len,mCase=0;
    while(~scanf("%s",str)){
        root=new Trie;
        for(i=0; i<MAX; i++)
            root->next[i]=NULL;
        memset(dp,0,sizeof(dp));
        len=strlen(str);
        scanf("%d",&S);
        while(S--){
            scanf("%s",str2);
            createTrie(str2);
        }

        dp[len]=1;
        for(i=len-1;i>=0;--i)
            dp[i]=findTrie(str,i,len);

        printf("Case %d: %d\n",++mCase,dp[0]);
        delete(root);
    }
    return 0;
}

时间: 2024-12-15 12:38:51

UVA - 1401 Remember the Word(trie+dp)的相关文章

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]的前缀,在所给的单词中查找前缀,如果存在,则进行状态

UVA 11361 - Investigating Div-Sum Property(数位DP)

题目链接:11361 - Investigating Div-Sum Property 白书上的例题,不过没有代码,正好前几天写了一题数位DP的题目,这题也就相对轻松了. dp[i][x][y]表示加到第i位,数字 % k,数位和 % k的组合情况数,那么现在要添加一个0 - 9的数字上去状态转移为 dp[i + 1][(x * 10 + num) % k][(y + num) % k],计算总和后,由于数字本身不能超过最大值,所以最后还要添加上恰好前几位都为最大值的情况.然后最后在判断一下该数

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

LA 3942 Remember the Word (Trie树)

——刘汝佳的白皮书里面介绍的题目. /* Problem: Status : By WF, */ #include "algorithm" #include "iostream" #include "cstring" #include "cstdio" #include "string" #include "stack" #include "cmath" #inclu

UVALive - 3942 - Remember the Word (Trie树)

UVALive - 3942 Remember the Word Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Neal is very curious about combinatorial problems, and now here comes a problem about words. Knowing that Ray has a p

UVA 12063 Zeros and Ones(三维dp)

题意:给你n.k,问你有多少个n为二进制的数(无前导零)的0与1一样多,且是k的倍数 题解:对于每个k都计算一次dp,dp[i][j][kk][l]表示i位有j个1模k等于kk且第一位为l(0/1) 再次预处理mod[i][j]表示1的i次方模j等于几,具体看代码注释 import java.util.Scanner; public class Main{ static int Maxn=65; static int Maxk=101; //前i个数有j个1模给定的值余k且第一位为1或者0的总个

UVa 11270 铺放骨牌(轮廓线DP)

https://vjudge.net/problem/UVA-11270 题意: 用1×2骨牌覆盖n×m棋牌,有多少种方法? 思路: 这道题目是典型的轮廓线DP题. 所谓轮廓线DP,就是以整行整列为状态进行动态规划时无法进行状态转移,那么此时就可以用到轮廓线,当然,这种方法只能使用在一个窄棋盘上,大了肯定是不行的,要超时! ' 轮廓线DP就是按照从上到下,从左到右的顺序进行状态转移,每个格子用二进制来表示状态,1代表的就是覆盖,0代表未覆盖. 以本题为例,如上图,我们现在要计算 k 格子,那么与

uva 10391复合词compound words(Trie+set)

给定一个词典,要求求出其中所有的复合词,即恰好有两个单词连接而成的词 trie存储以该单词为前缀的单词数量,然后对于每个单词,看在字典中的以该单词为前缀的单词"减去"原单词剩下的单词是否在字典中,如果是储存这个答案到ans的set中 #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include&l

UVA 12063 Zeros and Ones (数位dp)

Binary numbers and their pattern of bits are always very interesting to computer programmers. In this problem you need to count the number of positive binary numbers that have the following properties: The numbers are exactly N bits wide and they hav