LA 3942 Remember the Word (Trie树)

——刘汝佳的白皮书里面介绍的题目。

/*
Problem:
Status :
By WF,
*/
#include "algorithm"
#include "iostream"
#include "cstring"
#include "cstdio"
#include "string"
#include "stack"
#include "cmath"
#include "queue"
#include "set"
#include "map"

#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1

typedef long long ll;
typedef unsigned long long ull;
using namespace std;

const int inf=0x3f3f3f3f;
const int maxn=1e6+5;
const int mod=20071027;

char str[maxn];
char word[maxn];
int dp[maxn];
int n;

struct Trie
{
    int sz;
    int ch[maxn][26];
    int val[maxn];

    void Init()
    {
        sz=1;
        val[0]=0;
        memset(ch[0],0,sizeof ch[0]);

    }

    void Insert(char *s)
    {
        int n = strlen(s);
        int u = 0;
        for(int i=0;i<n;++i)
        {
            if( ch[u][ s[i]-‘a‘ ] ==0 )
            {
                memset(ch[sz],0,sizeof ch[sz]);//!!
                val[sz]=0;
                ch[u][ s[i]-‘a‘ ] = sz;
                sz++;
            }
            u = ch[u][ s[i]-‘a‘ ];
        }
        val[u]=n;
        //printf("insert:%s\n",s);
    }

    void Search(char * s,int k,int l)
    {
        int u = 0;
        for(int i=0;i<l;++i)
        {
            if( ch[u][ s[i]-‘a‘ ]==0 )return;
            u = ch[u][ s[i]-‘a‘ ];
            if( val[u] )
            {
                /*
                for(int j=0;j<val[u];++j)
                {
                    printf("%c",s[j]);
                }
                printf("\n");
                */
                dp[k] = ( dp[k] + dp[k+val[u] ] )%mod;
                //printf("dp[%d]=%d   %d\n",k,dp[k],val[u]);
            }
        }
    }
}trie;

int main()
{
    //freopen("in.txt","r",stdin);
    int cs=1;
    while( scanf("%s",&str)!=EOF )
    {
        trie.Init();

        scanf("%d",&n);
        for(int i=0;i<n;++i)
        {
            scanf("%s",&word);
            trie.Insert(word);
        }
        int len = strlen(str);
        dp[len]=1;
        for(int i=len-1;i>=0;--i)
        {
            dp[i]=0;
            trie.Search(str+i,i,len-i);
        }
        printf("Case %d: %d\n",cs++,dp[0]);
    }

    return 0;
}

  

时间: 2024-12-13 08:00:56

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 字典树+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 入门)

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

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

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

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

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 题目大意: 给定一个字符串和给定一个单词集合.问从给定单词集合中选取单词,有多少种选取方法刚好拼接成字符串. 例如: abcd 4 a b cd ab 有两种 a-b-cd ab-cd 这两种情况 解题思路: 因为给定的字符串的长度是3*10^5所以暴力就不能解决问题了

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