思路:

大白里Trie的例题,开篇就是一句很容易推出....orz

这里需要Trie+DP解决。

仔细想想我们可以得到dp[i]=sum(dp[i+len[x]])。

这里需要解释一下:dp是从最后一个字母往前dp,dp[i]代表从i这个字符开始到最后一个字符的这个字符串(就是s[i,i+1,...,L])所能拆分的个数,所以我们每次查询s[i,i+1,...,k]是否存在这个前缀,都的话就加上dp[k+1],最后答案是dp[0]。注意dp[L+1]应该初始化为1,因为整个s[i,i+1,...,L]都是前缀就要+1种拆分方法。

这里Trie用的大白模板,自己写的一直超时也不知道为什么,把大白模板的结构体去掉也超时emmm,求大神讲解

5.15更新:今天一直尝试终于知道为什么超时了,因为之前每次query()都会计算一次s的长度,如果s很长,询问也很多,那么在strlen()上就会费很多时间(居然是这个原因orz),现在附上我自己的指针版

第二次代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<cmath>
#include<string>
#include<stack>
#include<set>
#include<map>
#include<vector>
#include<iostream>
#include<algorithm>
#include<sstream>
#define ll long long
const int N=300005;
const int MOD=20071027;
using namespace std;
char s[N];
int dp[N];
struct Trie{
Trie *next[26];
int num;
Trie(){
num=0;
for(int i=0;i<26;i++){
next[i]=NULL;
}
}
};
Trie *root;
void insert(char a[]){
int len=strlen(a);
Trie *p=root;
for(int i=0;i<len;i++){
int v=a[i]-'a';
if(p->next[v]==NULL) p->next[v]=new Trie();
p=p->next[v];
}
p->num=1;
}
int query(char a[],int head,int len){
Trie *p=root;
int res=0;
for(int i=head;i<len;i++){
int v=a[i]-'a';
if(!p->next[v]) return res;
p=p->next[v];
if(p->num){
res+=dp[i+1];
res%=MOD;
}
}
return res;
}
void del(Trie *p){
if(p==NULL) return;
for(int i=0;i<26;i++){
if(p->next[i]) del(p->next[i]);
}
delete p;
}
int main(){
char a[105];
int num;
int k=1;
while(~scanf("%s",s)){
root=new Trie();
scanf("%d",&num);
for(int i=0;i<num;i++){
scanf("%s",a);
insert(a);
}
int len=strlen(s);
dp[len]=1;
for(int i=len-1;i>=0;i--){
dp[i]=query(s,i,len); //这里一定要直接传入len,不然重新算会超时
}
printf("Case %d: %d\n",k++,dp[0]);
del(root);
}
return 0;
}

第一次代码(数组版):

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<cmath>
#include<string>
#include<stack>
#include<set>
#include<map>
#include<vector>
#include<iostream>
#include<algorithm>
#include<sstream>
#define ll long long
const int N=300005;
const int MOD=20071027;
using namespace std;
char s[N];
int dp[N];
struct Trie
{
int ch[4*N][26];
int val[4*N];
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[105];
int num;
int k=1;
while(~scanf("%s",s)){
T.reset();
memset(dp,0,sizeof(dp));
scanf("%d",&num);
for(int i=0;i<num;i++){
scanf("%s",a);
T.insert(a);
}
int len=strlen(s);
dp[len]=1;
for(int i=len-1;i>=0;i--){
dp[i]=T.query(s,i);
}
printf("Case %d: %d\n",k++,dp[0]);
}
return 0;
}

UVA 3942 Remember the Word (Trie+DP)题解的更多相关文章

  1. UVALive - 3942 Remember the Word[Trie DP]

    UVALive - 3942 Remember the Word Neal is very curious about combinatorial problems, and now here com ...

  2. UVA 1401 - Remember the Word(Trie+DP)

    UVA 1401 - Remember the Word [题目链接] 题意:给定一些单词.和一个长串.问这个长串拆分成已有单词,能拆分成几种方式 思路:Trie,先把单词建成Trie.然后进行dp. ...

  3. LA 3942 && UVa 1401 Remember the Word (Trie + DP)

    题意:给你一个由s个不同单词组成的字典和一个长字符串L,让你把这个长字符串分解成若干个单词连接(单词是可以重复使用的),求有多少种.(算法入门训练指南-P209) 析:我个去,一看这不是一个DP吗?刚 ...

  4. UVA - 1401 | LA 3942 - Remember the Word(dp+trie)

    https://vjudge.net/problem/UVA-1401 题意 给出S个不同的单词作为字典,还有一个长度最长为3e5的字符串.求有多少种方案可以把这个字符串分解为字典中的单词. 分析 首 ...

  5. 【UVA1401】Remember the Word Trie+dp

    题目大意:给定一个字符串和一个字符串集合,问从集合中选出若干个串组成给定母串的不同方案数. 题解:有些类似于背包问题.状态很好表示,为:\(dp[i]\) 表示母串前 i 个字符的不同方案数,因此,有 ...

  6. Trie + DP LA 3942 Remember the Word

    题目传送门 题意:(训练指南P209) 问长字符串S能由短单词组成的方案数有多少个 分析:书上的做法.递推法,从后往前,保存后缀S[i, len-1]的方案数,那么dp[i] = sum (dp[i+ ...

  7. LA 3942 Remember the Word(前缀树&树上DP)

    3942 - Remember the Word Neal is very curious about combinatorial problems, and now here comes a pro ...

  8. UVALive 3942 Remember the Word 字典树+dp

    /** 题目:UVALive 3942 Remember the Word 链接:https://vjudge.net/problem/UVALive-3942 题意:给定一个字符串(长度最多3e5) ...

  9. LA 3942 - Remember the Word 字典树+DP

    看题传送门:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show ...

随机推荐

  1. Connections in Galaxy War----zoj3261

    题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3261 题意:有n个星球编号为0—n-1;能量分别为p[i]:有 ...

  2. 蔡勒(Zeller)公式--黑色星期五

    求某年某月某日是周几; 蔡勒(Zeller)公式: w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1 ;y是年的后两位:c是世纪数-1(年的前两位):m是月份,大于等于3,小于等 ...

  3. NYOJ 275 队花的烦恼一

    队花的烦恼一 时间限制:3000 ms  |  内存限制:65535 KB 难度:1 描写叙述 ACM队的队花C小+常常抱怨:"C语言中的格式输出中有十六.十.八进制输出,然而却没有二进制输 ...

  4. vue-moment的使用

    1.安装:npm install moment --save 2.导入:import moment from 'moment'; 3.定义全局时间过滤器:  Vue.filter('converDat ...

  5. 编译错误 ----- /usr/bin/ld: cannot find -lc

    yum install glibc-static glib-static是Gcc链接时使用到的库.

  6. CloudFlare CDN折腾记-优化设置

    近期又在折腾了,常访问我博客的朋友或许页面曾出现过502错误提示,那是折腾CloudFlare CDN不成功的提示.在此先感谢坛子,在他的执着和求真之下,昨天晚上终于成功使用上CloudFlare C ...

  7. 识别真假搜索引擎(搜索蜘蛛)方法(baidu,google,Msn,sogou,soso等)

    http://www.useragentstring.com/pages/useragentstring.php 今天分析研究了两个网站的 Apache 日志,分析日志虽然很无聊,但却是很有意义的事情 ...

  8. LeetCode--687. 最长同值路径

    题目描述:给定一个二叉树,找到最长的路径,这个路径中的每个节点具有相同值.这条路径可以经过也可以不经过根节点.注意:两个节点之间的路径长度由它们之间的边数表示. 示例1:输入: 5 / \ 4 5 / ...

  9. TFS修改映射路径办法

    如果你之前配置好了TFS项目的映射路径.然后每次下载项目都会在你配置的路径,但我们可以修改 方法一:我们可以在 "工作区" 中修改路径

  10. file_get_post实现post请求

    function Post($url, $post = null){     $context = array();     if (is_array($post)) {       ksort($p ...