思路:

大白里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. sql批量修改wordpress文章发布时间

    有时为了体现wordpress文章的更新程度,会在后台那边重新设置发布时间,有没更简单的方法呢?用sql批量修改wordpress文章发布时间怎么操作呢? UPDATE `wp_posts` SET ...

  2. Core Data with Mantle

    Mantle makes it easy to write a simple model layer for your Cocoa or Cocoa Touch application.  Mantl ...

  3. vue-moment的使用

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

  4. 在centos7下安装svn

    SVN的安装 yum install subversion 服务端命令 1. svnserver - 控制svn系统服务的启动等 2. svnadmin - 版本库的创建/导出/导入/删除等 3. s ...

  5. idea 连接数据库

    1:如果没有数据库连接插件,下载database插件 settings>plugin>Database Navigator 下载. 2:重启 3:进入 view>tool windo ...

  6. Spark会把数据都载入到内存么?

    前言 很多初学者其实对Spark的编程模式还是RDD这个概念理解不到位,就会产生一些误解. 比如,很多时候我们常常以为一个文件是会被完整读入到内存,然后做各种变换,这很可能是受两个概念的误导: RDD ...

  7. spring boot整合JWT例子

    application.properties jwt.expire_time=3600000 jwt.secret=MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjY34DFDSS ...

  8. C++(STL)&&树-堆结构练习——合并果子之哈夫曼树

    题目题解:http://blog.csdn.net/xu12110501127/article/details/9199335 有关博客:http://www.360doc.com/content/1 ...

  9. word2vec原理(一) CBOW+Skip-Gram模型基础

    word2vec是google在2013年推出的一个NLP工具,它的特点是将所有的词向量化,这样词与词之间就可以定量的去度量他们之间的关系,挖掘词之间的联系.本文的讲解word2vec原理以Githu ...

  10. Perl的debug小技巧

    进入Perl的调试环境的命令:  Perl  -d  perl_file 设置断点:b + perl代码中的行号. 执行到断点:c 表示continue until breakpoint. 执行下一条 ...