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

析:我个去,一看这不是一个DP吗?刚开始交一直是runtime error,找了好久,一直以为是数组开小了,不断增大还是这样,后来发现我用了char类型。。。下面分析这个题目

应该不难想到这个状态转移方程:

d(i) = sum{d(i+len(x))|单词x是s[i...L]的前缀},其中len(x)是长度。d(i)表示从字符i开始的字符串(也就是后缀s[i...L])的种数。

很明显我们是从后往前递推的,d(i)的种数应该是由d(i)和d(i+len(x))的和组成的(想想为什么,不理解可以画个图分析一下)。

如果先枚举x,再判断它是不是s[i...L]的前缀,时间复杂度太高了。所以换一个思路,先把单词组成Tire(前缀树),然后试着在Tire中去找s[i..L]。具体参考代码。

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring> using namespace std;
const int maxn = 4000 * 100 + 10; // 4000个单词,每个单词最长是100,最多就有这么多
const int maxm = 300010;
const int mod = 20071027;
int d[maxm];
char ss[maxm], t[110]; struct Tire{
int ch[maxn][26];
int val[maxn];
int sz;
void init() { sz = 1; memset(val, 0, sizeof(val)); memset(ch[0], 0, sizeof(ch[0])); } //初始化
int idx(char c){ return c - 'a'; } //获得编号 void inser(char *s){ // 插入
int u = 0, n = strlen(s);
for(int i = 0; i < n; ++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] = n;
} void quary(char *s, int i, int n){ // 查找
int u = 0;
for(int j = 0; j < n; ++j){
int c = idx(s[j]);
if(!ch[u][c]) return ;
u = ch[u][c];
if(val[u]) d[i] = (d[i] + d[i + val[u]]) % mod;
}
}
};
Tire tire; int main(){
int n, kase = 0;
while(~scanf("%s %d", ss, &n)){
tire.init(); //一定要初始化,刚开始Tire定义在里面,一运行就崩。。。我也是醉了 for(int i = 0; i < n; ++i){
scanf("%s", t);
tire.inser(t);
} memset(d, 0, sizeof(d));
int len = strlen(ss);
d[len] = 1;// 这个地方是边界,注意初始化 for(int i = len-1; i >= 0; --i)
tire.quary(ss+i, i, len-i); //递推种数
printf("Case %d: %d\n", ++kase, d[0]);
}
return 0;
}

LA 3942 && UVa 1401 Remember the Word (Trie + DP)的更多相关文章

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

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

  2. UVA 1401 Remember the Word(用Trie加速动态规划)

    Remember the Word Neal is very curious about combinatorial problems, and now here comes a problem ab ...

  3. UVA - 1401 Remember the Word(trie+dp)

    1.给一个串,在给一个单词集合,求用这个单词集合组成串,共有多少种组法. 例如:串 abcd, 单词集合 a, b, cd, ab 组合方式:2种: a,b,cd ab,cd 2.把单词集合建立字典树 ...

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

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

  5. UVA 1401 Remember the Word

    字典树优化DP                                Remember the Word Time Limit: 3000MS   Memory Limit: Unknown ...

  6. 【UVA1401】Remember the Word Trie+dp

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

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

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

  8. Trie + DP LA 3942 Remember the Word

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

  9. UVA 3942 Remember the Word (Trie+DP)题解

    思路: 大白里Trie的例题,开篇就是一句很容易推出....orz 这里需要Trie+DP解决. 仔细想想我们可以得到dp[i]=sum(dp[i+len[x]]). 这里需要解释一下:dp是从最后一 ...

随机推荐

  1. DrawDib 使用例子<转>

    #include<vfw.h>#pragma comment(lib,"Vfw32.lib") BITMAPINFOHEADER biHeader; memset(&a ...

  2. Inspector视图中的get/set使用

    using UnityEngine; using System.Collections; public class Test : MonoBehaviour { public int width { ...

  3. C++ 0x 使用可变参数模板类 实现 C# 的委托机制

    #ifndef _ZTC_DELEGATE_H_ #define _ZTC_DELEGATE_H_ #include <vector> #include <functional> ...

  4. sessionStorage和localStorage

    html5中的Web Storage包括了两种存储方式:sessionStorage和localStorage. sessionStorage用于本地存储一个会话(session)中的数据,这些数据只 ...

  5. vcf格式简介

    1)背景 伴随着大规模的基因分型及测序工程的产生(例如1000 Genomes Project),之前的信息贮存格式例如gff文件它记录了每一个基因的详细信息,其中许多基因信息在基因组之间是共享的,而 ...

  6. HttpClient 4 和 HttpClient 3 超时

    HttpClient 4: 连接超时: httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,6000 ...

  7. ie6浏览器的安装

    试过各种方法都不行,最后用ie8卸载工具,不仅卸载了ie8还自动安装了ie6,非常棒!!!我的空间有那款卸载工具.

  8. Linux 线程调度

    1.线程sleep()后,会让出cpu的时间片,交由其他线程进行抢占cpu. 线程之间正常的切换是依靠时间片的. 当主线程没有结束,且其在所占有的时间片内,并没有结束自己的工作,此时,子线程将会抢占c ...

  9. swift UIAlertController使用 UIAlertController的宽度 为270

    添加子控件 1. 有标题, alert标题高度大概 是 40, 子控件的 Y一般在40 ,如果中间有换行, \n 的高度大概是30 2.alert的宽度 是270, 设置frame 的时候注意 /// ...

  10. AndroidStudio 导包遇到so文件的解决方案----------JPush推送

    最近遇到 Couldn't load jpush175 from loader dalvik.system.PathClassLoader 这样一个问题 它说的是AS不能找到库文件 发生在于像Ecli ...