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

#include<iostream>
#include<cstring>
#include<cstdio>
#define maxnode 400001
#define sigma_size 26
#define M 300001
#define mod 20071027
using namespace std;
char str[M];
int dp[M];
struct Trie
{
    int ch[maxnode][sigma_size];
    int val[maxnode];
    int sz;
    void reset(){memset(ch[0],0,sizeof ch[0]);memset(val,0,sizeof val);sz=1;}

    int idx(char c){return c-'a';}
    void insert(char *s)
    {
        int u=0,l=strlen(s);
        for(int i=0;i<l;++i){
            int c=idx(s[i]);
            if(!ch[u][c]){
                memset(ch[sz],0,sizeof ch[sz]);
                ch[u][c]=sz++;
            }
            u=ch[u][c];
        }
        val[u]=1;
    }

    int query(char *s,int p)
    {
        int u=0,l=strlen(s),res=0;
        for(int i=p;i<l;++i){
            int c=idx(s[i]);
            if(!ch[u][c]) return res;
            u=ch[u][c];
            if(val[u]){
                res+=dp[i+1];
                res%=mod;
            }
        }
        return res;
    }
}T;
int main()
{
    char a[110];
    int cas=1;
    while(scanf("%s",str)!=EOF){
        memset(dp,0,sizeof dp);
        int n;
        T.reset();
        scanf("%d",&n);
        for(int i=0;i<n;++i){
            scanf("%s",a);
            T.insert(a);
        }
        int l=strlen(str);
        dp[l]=1;
        for(int i=l-1;i>=0;--i){
            dp[i]=T.query(str,i);
        }
        printf("Case %d: %d\n",cas++,dp[0]);
    }
    return 0;
}

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

时间: 2024-08-08 09:42:14

LA ——3942 - Remember the Word(Trie 入门)的相关文章

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>

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

单词拆解&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

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所以暴力就不能解决问题了

LA 3942 Remember the Word

已知一些单词,选择其中一些单词组成目的字符串,问共有多少种方法.其实初看到这道题,自然而然地可以想到动态规划中经典的硬币问题:例如,问1元,2元,5元,总共有多少种方法能组成20元?这里不过是把硬币换成了单词而已.但是,如果真的只是像硬币问题一样每个单词都轮询一遍,显然太慢了,最多要有300000*4000*100次比对. 假如利用trie数的话,至多只要比对100次,就能找到所有匹配的单词.然后将字符串从左至右DP即可.设d[i]表示从位置i开始的后缀的解,已知d[i]~d[n],那么求d[i

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为短字符

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

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写了一遍,各种出错,整个人都不好了... 研究了一遍别人代码,发现快