LA3942 Remember the Word(Trie+DP)

Trie图的简单应用。这题关键是想出递推式。令d(i)表示从字符i开始的字符串,d(i)=sum{d(i+len(x))},x是s[i...L]的前缀。然后把所有可分解成的单词构造成一颗Trie树,再让母串在上面跑,d[0]即是方案总数。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mod 20071027
#define M 400005
using namespace std;

int n,top,len;
int tree[M][27];
char S[M];
char p[105];
int val[M];
int d[M];

void init()
{
    top=1;
    memset(tree,0,sizeof(tree));
    memset(d,0,sizeof(d));
}

int idx(char c)
{
    return c-'a';
}

void insert(char *s)
{
    int Len=strlen(s);
    int u=0;
    for(int i=0;i<Len;i++)
    {
        int c=idx(s[i]);
        if(!tree[u][c])
        {
            val[top]=0;
            tree[u][c]=top++;
        }
        u=tree[u][c];
    }
    val[u]=1;
}

int query(char *s,int start)
{
    int count=0;
    int u=0;
    for(int i=start;i<len;i++)
    {
        int c=idx(s[i]);
        u=tree[u][c];
        if(!u) return count;
        if(val[u])
        {
            count+=d[i+1];
            count%=mod;
        }
    }
    return count;
}

int main()
{
    int t=1;
    //freopen("d:\\test.txt","r",stdin);
    while(scanf("%s",S)!=EOF)
    {
        scanf("%d",&n);
        init();
        for(int i=0;i<n;i++)
        {
            scanf("%s",p);
            insert(p);
        }
        len=strlen(S);
        d[len]=1;
        for(int i=1;i<=len;i++)
        {
            d[len-i]=query(S,len-i);
        }
        cout<<"Case "<<t++<<": "<<d[0]<<endl;
    }
    return 0;
}
时间: 2024-11-05 17:24:14

LA3942 Remember the Word(Trie+DP)的相关文章

UVALive - 3942 Remember the Word[Trie DP]

UVALive - 3942 Remember the Word Neal is very curious about combinatorial problems, and now here comes a problem about words. Know- ing that Ray has a photographic memory and this may not trouble him, Neal gives it to Jiejie. Since Jiejie can’t remem

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

【UVA1401】Remember the Word Trie+dp

题目大意:给定一个字符串和一个字符串集合,问从集合中选出若干个串组成给定母串的不同方案数. 题解:有些类似于背包问题.状态很好表示,为:\(dp[i]\) 表示母串前 i 个字符的不同方案数,因此,有状态转移方程为:\(dp[i]=\Sigma dp[j],s[j+1...i]=s_0,s_0\in set\) ,可以发现若枚举 \(j < i\) 作为决策集合的话,时间复杂度将是 \(O(n^2)\) 的.优化:可以用 Trie 来直接进行匹配,具体操作如下:将每个集合中的串倒序插入 Trie

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开始

UVALive 3942 - Remember the Word(DP,数组Trie+指针Trie)

UVALive 3942 - Remember the Word(DP,数组Trie+指针Trie) ACM 题目地址: UVALive 3942 - Remember the Word 题意: 给一些单词,然后给一个长的单词,问有几种方法能组成这个大单词,单词可以重复用. 分析: DP[i]=sum{DP[j} (i<j<len),从后往前求. 本来用数组Trie写得爽爽的,1A了. 发现2s多,不能忍! 然后用指针Trie写了一遍,各种出错,整个人都不好了... 研究了一遍别人代码,发现快

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 s

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

hdu 4570 Multi-bit Trie(dp)

题目链接:hdu 4570 Multi-bit Trie 题意: 这题的题意要看半天,其实就是让你求∑ai*(2^bi),一个长度为n的数列,将其分成若干段(每一段的长度要<=20), 要求∑ai*(2^bi)最小,其中ai是每一段数列的第一项,bi是每一段的长度. 比如样例:1 2 4 4 5 4 3,将其分成1 2 4| 4 5| 4| 3, 则其所用空间为1*2^3+4*2^2+4*2^1+3*2^1=38. 题解: 考虑dp[i]表示前i个分好后的最优解,则有dp[i]=min(dp[i