UVA 3942 Remember the Word (Trie+DP)题解
思路:
大白里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)题解的更多相关文章
- UVALive - 3942 Remember the Word[Trie DP]
UVALive - 3942 Remember the Word Neal is very curious about combinatorial problems, and now here com ...
- UVA 1401 - Remember the Word(Trie+DP)
UVA 1401 - Remember the Word [题目链接] 题意:给定一些单词.和一个长串.问这个长串拆分成已有单词,能拆分成几种方式 思路:Trie,先把单词建成Trie.然后进行dp. ...
- LA 3942 && UVa 1401 Remember the Word (Trie + DP)
题意:给你一个由s个不同单词组成的字典和一个长字符串L,让你把这个长字符串分解成若干个单词连接(单词是可以重复使用的),求有多少种.(算法入门训练指南-P209) 析:我个去,一看这不是一个DP吗?刚 ...
- UVA - 1401 | LA 3942 - Remember the Word(dp+trie)
https://vjudge.net/problem/UVA-1401 题意 给出S个不同的单词作为字典,还有一个长度最长为3e5的字符串.求有多少种方案可以把这个字符串分解为字典中的单词. 分析 首 ...
- 【UVA1401】Remember the Word Trie+dp
题目大意:给定一个字符串和一个字符串集合,问从集合中选出若干个串组成给定母串的不同方案数. 题解:有些类似于背包问题.状态很好表示,为:\(dp[i]\) 表示母串前 i 个字符的不同方案数,因此,有 ...
- Trie + DP LA 3942 Remember the Word
题目传送门 题意:(训练指南P209) 问长字符串S能由短单词组成的方案数有多少个 分析:书上的做法.递推法,从后往前,保存后缀S[i, len-1]的方案数,那么dp[i] = sum (dp[i+ ...
- LA 3942 Remember the Word(前缀树&树上DP)
3942 - Remember the Word Neal is very curious about combinatorial problems, and now here comes a pro ...
- UVALive 3942 Remember the Word 字典树+dp
/** 题目:UVALive 3942 Remember the Word 链接:https://vjudge.net/problem/UVALive-3942 题意:给定一个字符串(长度最多3e5) ...
- LA 3942 - Remember the Word 字典树+DP
看题传送门:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show ...
随机推荐
- LightOj 1030 - Discovering Gold(dp+数学期望)
题目链接:http://lightoj.com/volume_showproblem.php?problem=1030 题意:在一个1*n 的格子里,每个格子都有相应的金币数,走到相应格子的话,就会得 ...
- 在本机搭建vue-cli3项目
vue-cli3官方网址: https://cli.vuejs.org/zh/ 由于公司开始一个新项目,用到的是vue-cli3搭建的项目,所以自己想搭建一个项目,今天搭建的项目就是一个很简单的项目, ...
- Frame报文
链路层帧常用的帧格式有两种:Ethernet II 与 IEEE802.3 Ethernet II 格式多用于终端设备的通信 IEEE802.3 格式多用于网络设备的通信 如何区分这两种报文 ...
- django源码笔记-【2】(转)
add by zhj: 在原文的基础上有修改 原文:http://www.cnblogs.com/gaott/archive/2012/02/28/2371238.html 上一期完理解了WSGI处理 ...
- Jsoup爬虫解析
需要下载jsoup-1.8.1.jar包 jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址.HTML文本内容.它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQue ...
- 怎样在 Ubuntu 上使用 ZFS 文件系统 | Linux 中国
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/F8qG7f9YD02Pe/article/details/79329762 http://mmbiz ...
- [django实践]投票app
code: https://github.com/lannyMa/toupiao polls app介绍 这个例子来源于django官网,恰好2.x版本有中文版. https://docs.djang ...
- [LeetCode] 836. Rectangle Overlap_Easy
A rectangle is represented as a list [x1, y1, x2, y2], where (x1, y1) are the coordinates of its bot ...
- Toaster
https://wiki.opendaylight.org/view/YANG_Tools:YANG_to_Java_Mapping#Identity https://wiki.opendayligh ...
- ios 工作日志
1.设计模式 1.1 想用一个controllerK控制多个页面的切换 但是每一个页面必须要引用这个controller,这样才能控制进度, 所以必须是弱引用.controller必须被某一个实例强引 ...