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 ...
随机推荐
- Is It A Tree?----poj1308
http://poj.org/problem?id=1308 #include<stdio.h> #include<string.h> #include<iostream ...
- 关于微信小程序,你想知道的他们都问了
微信公开课深圳站小程序专场刚刚结束,大家通过"微信公开课+"互动小程序提出了许多问题.我们筛选了后台问得最多的九个问题进行解答,快来看看这里有没有你想要的答案吧! @谢杨:小程序是 ...
- Spring boot Security 用于权限管理,用户添加等。
1:添加依赖: <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thy ...
- hdu1181 (变形课)简单地dfs
http://acm.sdut.edu.cn:8080/vjudge/contest/view.action?cid=259#problem/F Description 呃......变形课上Harr ...
- malloc 实现原理
1. Reference: 如何实现一个malloc http://blog.codinglabs.org/articles/a-malloc-tutorial.html 2.
- 翻译[RFC6238] TOTP: Time-Based One-Time Password Algorithm
在闲暇时间做了一个TOTP相关的开源项目,在项目初步完成之余,我尝试对[RFC6238]文档进行了翻译,供大家参考与查阅,若有不妥之处,还望各位前辈海涵斧正. [RFC6238] : Time-Bas ...
- python学习第一次
一,安装python 官网下载地址:https://www.python.org/downloads/windows/ 我下载的是最新的: Download Windows x86 web-based ...
- VS2010/MFC编程入门之三十五(菜单:菜单及CMenu类的使用)
鸡啄米在上一节中讲的是VS2010的菜单资源,本节主要讲菜单及CMenu类的使用. CMenu类的主要成员函数 MFC为菜单的操作提供了CMenu类,下面鸡啄米就常用的几个成员函数进行简单的介绍. B ...
- Linux中顿号
``的作用是运行``之间的命令,并且将命令运行的结果返回.一般shell脚本应该是这样:result=`ls -l` (用你的命令替换ls -l,这里只是举例)这样,result就有``里面的运行结果 ...
- caffe 中base_lr、weight_decay、lr_mult、decay_mult代表什么意思?
在机器学习或者模式识别中,会出现overfitting,而当网络逐渐overfitting时网络权值逐渐变大,因此,为了避免出现overfitting,会给误差函数添加一个惩罚项,常用的惩罚项是所有权 ...