LA、Remember the Word (字典树, 简单dp)

传送门

题意: 给你一个初始串 S,strlen(s) <= 3e5  然后给你 n 个单词。 n <= 4000,  每个单词的长度不超过 100 ;

   问你这个初始串,分割成若干个单词的连接的方案;(这些单词必须是给定的n个单词中的任意一个,一个单词可以被使用多次。)

解: 将 n 个单词建个字典树;

   dp[ i ] 表示,S的 0 ~ i - 1 切割成若干个 单词的方案数;

   枚举S, 枚举到 当前位置 i; 然后就在字典树找,以 S 的 i + 1 开始的, 能不能找到一个单词与之匹配;

   若能找到, 假设单词为 i + 1 ~ j; 那么就有 dp[ j + 1 ] = ( dp[ j + 1 ] + dp[ i ] ) % mod

    这只是个简单dp; 和字典树的简单应用的结合。

#include <bits/stdc++.h>
#define LL long long
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3f3f3f3f
#define mem(i, j) memset(i, j, sizeof(i))
#define pb push_back
using namespace std;

const int mod = 20071027;

const int N = 3e5 + 5, M = 4e5 + 5;
char s[N], b[105];
int a[M][40], tot, vis[N], dp[N];
int get(char x) {
    return x - ‘a‘;
}
void join() {
    int now = 0;
    rep(i, 0, (int)strlen(b) - 1) {
        int id = get(b[i]);
        if(!a[now][id]) {
            mem(a[tot], 0); vis[tot] = 0;
            a[now][id] = tot++;
        }
        now = a[now][id];
    }
    vis[now] = 1;
}
int main() {
    int cas = 0;
    while(~scanf("%s", s)) {
        int n; scanf("%d", &n); tot = 1;
        mem(a[0], 0);
        rep(i, 1, n) {
            scanf("%s", b); join();
        }
        mem(dp, 0); dp[0] = 1;
        rep(i, 0, (int)strlen(s) - 1) {
            int now = 0;
            rep(j, i, (int)strlen(s) - 1) {
                int id = get(s[j]);
                if(!a[now][id]) break;
                now = a[now][id];
                if(vis[now]) {
                    dp[j + 1] = (dp[j + 1] + dp[i]) % mod;
                }
            }
        }
        printf("Case %d: ", ++cas);
        printf("%d\n", dp[(int)strlen(s)]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Willems/p/11980244.html

时间: 2024-11-10 16:16:08

LA、Remember the Word (字典树, 简单dp)的相关文章

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

HDU 3016 Man Down 线段树+简单DP

囧,一开始看错题意,后来才发现人是垂直下落的,被附带链接里的Man Down游戏误导了. 那就变成了一个简单的DAG模型动态规划,随意搞就ok了 #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <set> #include <vector> #include <string> #include <queu

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

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

UVA 3942 -- Remember the Word (字典树+dp)

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

LA3942 Remember the Word(字典树+记忆化搜索)

题目:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=22109 题意:给出一个由S个不同单词组成的字典和一个长字符串.把这个字符串分解成若干个单词的连接(单词可以重复使用),由多少种方法?比如,有4个单词a,b,cd,ab,则abcd有两种分解方法:a+b+cd和ab+cd 分析:首先将输入的字典建成字典树.然后记忆化搜索~ 代码: #include <iostream> #include <cstring>

字典树简单运用--》去亿万条城市三字码数据中Check是否存在某个城市三字码

前言:不知不觉来C***P半年了,过得也算是不好不坏.遇到过出问题只会推给开发,一直抱怨却提不出方案的业务:也遇到过大V开头(可以问度娘)的水的冒泡的开发. 有两件小事和大家分享一下: 1)我们组的接口调用某个外部接口,有些条件下该外部接口会直接把exception(堆栈信息,代码物理路径也有..)抛给我们,我邮件给相关的测试和开发, 不出意外,没有回复:后来不知道他们搞什么鬼,想让我们把这个exception也Log下来... 2)说起这个大V开头的,也是我们要调用的某个外部接口的开发.简单描

Codeforces 1285D Dr. Evil Underscores(字典树,dp)

传送门 题意: 有一个长度为 \(n\ (1\leq n\leq 10^5)\)的整数序列 \(a_1,\cdots,a_n\ \ (0\leq a_i\leq 2^{30}-1)\),你需要找到一个非负整数 \(X\) 使得 \(\max(a_i\oplus X)\)最小,其中 \(\oplus\) 为按位异或运算. 输入这个序列,输出\(\max(a_i\oplus X)\)的最小值. 思路: 1.数组中的每个数的二进制下的某位(第k位)都是0或者是1,那么x的第k位取值是0或者1,使得答案

HDU4825/5536 [01 字典树/简单字典树更新]

Xor Sum Time Limit: 1000 MS Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大.Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助.你能证明人类的智慧么? Input 输入包含若干组测试数

字典树简单知识及类实现

什么是trie树? ◇ trie树是一种用于快速检索的多叉树结构. ◇ 和二叉查找树不同,在trie树中,每个结点上并非存储一个元素. ◇ trie树把要查找的关键词看作一个字符序列.并根据构成关键词字符的先后顺序构造用于检索的树结构. ◇在trie树上进行检索类似于查阅英语词典. 一棵m度的trie树或者为空,或者由m棵m度的trie树构成. 例如,电子英文词典,为了方便用户快速检索英语单词,可以建立一棵trie树.例如词典由下面的单词构成:a.b.c.aa.ab.ac.ba.ca.aba.a