UVALive - 3942 Remember the Word
input
字符串s 1<=len(s)<=300000
n 1<=n<=4000
word1
word2
...
wordn
1<=len(wordi)<=100
output
由一个或多个word拼成s的种数%20071027.
做法1:dp:单词长度最多为100,d[i]表示到第i个字符结束的种数,则如果d[j]到d[i]这段字符能从trie中找到,d[i]+=d[j],i-100<j<=i
//1225ms
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <cctype>
#define MAX 100000
#define LL long long
#define mod 20071027
struct trie
{
int ch[*MAX][];
bool val[*MAX];
int sz;
trie()
{
sz=;
memset(ch[],,sizeof(ch[]));
}
int idx(char &c) { return c-'a';}
char* insert(char*s)
{
int u=;
for(;*s;s++)
{
int c=idx(*s);
if(!ch[u][c])
{
memset(ch[sz],,sizeof(ch[sz]));
val[sz]=;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]=;
return s;
}
int find(char*s,int n)
{
int u=;
for(int i=;i<n;i++)
{
int c=idx(s[i]);
if(!ch[u][c]) return ;
u=ch[u][c];
}
return val[u];
}
};
trie t;
char s[*MAX+],word[];
int n,maxl,d[*MAX+],cas=;
int main()
{
//freopen("/home/user/桌面/in","r",stdin);
while(scanf("%s",s)==)
{
memset(t.ch[],,sizeof(t.ch[]));
t.sz=;
scanf("%d",&n);
maxl=;
while(n--)
{
scanf("%s",word);
int l=t.insert(word)-word;
maxl=std::max(maxl,l);
}
n=strlen(s);
memset(d,,sizeof(d));
int u=,work=;
for(int i=;i<maxl;i++)
{
int c=t.idx(s[i]);
if(!t.ch[u][c]) break;
u=t.ch[u][c];
if(t.val[u])
{
work=;
d[i]=;
}
}
// for(int i=0;i<=n;i++) printf("%d ",d[i]);printf("\n");
if(work)
{
for(int i=;i<n;i++)
{
for(int j=;j<=maxl;j++)
{
if(i-j>=&&t.find(s+i-j+,j)) d[i]=(d[i]+d[i-j])%mod;
}
}
}
// for(int i=0;i<=n;i++) printf("%d ",d[i]);printf("\n");
printf("Case %d: %d\n",cas++,d[n-]);
}
//printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
return ;
}
dp
做法2:直接模拟:一开始只有一条路找,每个单词结束时分出一条路从头开始
//79ms
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <cctype>
#define MAX 100000
#define LL long long
#define mod 20071027
struct trie
{
int ch[*MAX][];
bool val[*MAX];
int sz;
trie()
{
sz=;
memset(ch[],,sizeof(ch[]));
}
int idx(char &c) { return c-'a';}
void insert(char*s)
{
int u=;
for(;*s;s++)
{
int c=idx(*s);
if(!ch[u][c])
{
memset(ch[sz],,sizeof(ch[sz]));
val[sz]=;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]=;
}
};
trie t;
char s[*MAX+],word[];
int n,cas=,head[][],count[][],num[];
int main()
{
//freopen("/home/user/桌面/in","r",stdin);
while(scanf("%s",s)==)
{
memset(t.ch[],,sizeof(t.ch[]));
t.sz=;
scanf("%d",&n);
while(n--)
{
scanf("%s",word);
t.insert(word);
}
int d=;
num[d]=;
head[d][]=;
count[d][]=;
for(char*p=s;*p;p++,d^=)
{
// printf("%d %d\n",count[d][0],d);
int &idx=num[d^]=;
int c=t.idx(*p);
head[d^][]=;
count[d^][]=;
for(int i=;i<num[d];i++)
{
int &f=head[d][i];
if(t.ch[f][c])//继续走到下一个字母
{
if(t.val[t.ch[f][c]])//走完一个单词,从头开始,总是head[d][0]
{
count[d^][]+=count[d][i];
count[d^][]%=mod;
}
head[d^][idx]=t.ch[f][c];
count[d^][idx++]=count[d][i];
}
}
}
// printf("%d %d\n",count[d][0],d);
printf("Case %d: %d\n",cas++,count[d][]);
}
//printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
return ;
}
模拟
UVALive - 3942 Remember the Word的更多相关文章
- UVALive - 3942:Remember the Word
发现字典里面的单词数目多且长度短,可以用字典树保存 f[i]表示s[i~L]的分割方式,则有f[i]=∑f[i+len(word[j])] 其中word[j]为s[i~L]的前缀 注意字典树又叫前 ...
- UVALive - 3942 Remember the Word[树状数组]
UVALive - 3942 Remember the Word A potentiometer, or potmeter for short, is an electronic device wit ...
- UVALive - 3942 Remember the Word[Trie DP]
UVALive - 3942 Remember the Word Neal is very curious about combinatorial problems, and now here com ...
- 【暑假】[实用数据结构]UVAlive 3942 Remember the Word
UVAlive 3942 Remember the Word 题目: Remember the Word Time Limit: 3000MS Memory Limit: Unknown ...
- UVALive 3942 Remember the Word 字典树+dp
/** 题目:UVALive 3942 Remember the Word 链接:https://vjudge.net/problem/UVALive-3942 题意:给定一个字符串(长度最多3e5) ...
- UVALive 3942 Remember the Word
题意:给出一个由S个不同单词组成的字典和一个长字符串.把这个字符串分解成若干个单词的连接(单词可以重复 使用),有多少种方法? Sample Input abcd 4 a b cd ab Sample ...
- Remember the Word UVALive - 3942(dp+trie)
题意: 给S个不同的单词和一个长字符串 问将其分解为若干个单词有多少种方法(单词可重复使用) 解析: dp[i]表示在这个字符串中以某个位置i为起点的 的一段子字符串 则这个子字符串若存在某个前缀恰好 ...
- UVALive 3942 Remember The Word (Tire)
状态是DAG,因此方案用dp统计,dp[i] = sum(dp[i+len(x)]),x是以i开头的前缀且是单词,关键在于快速判断一个前缀是不是单词,可用Trie. 每一次转移的复杂度是O(maxle ...
- UVALive - 3942 Remember the Word (Trie + DP)
题意: 给定一篇长度为L的小写字母文章, 然后给定n个字母, 问有多少种方法用这些字母组成文章. 思路: 用dp[i]来表达[i , L]的方法数, 那么dp[i] 就可以从dp[len(x) + i ...
随机推荐
- HDU 1695 GCD#容斥原理
http://acm.hdu.edu.cn/showproblem.php?pid=1695 翻译题目:给五个数a,b,c,d,k,其中恒a=c=1,x∈[a,b],y∈[c,d],求有多少组(x,y ...
- bootcss
道友们,今天由贫道讲一下bootcss的编码规范: 首先黄金定律:一个项目一定要有一套编码规范,无伦项目有多少人参与都要一致. 用两个空格来代替制表符(tab) -- 这是唯一能保证在所有环境下获得一 ...
- 判断括号字符串是否为合法+求n对括号的所有组合
n对括号的有效组合数 参考:https://zh.wikipedia.org/wiki/%E5%8D%A1%E5%A1%94%E5%85%B0%E6%95%B0 import java.util.Ar ...
- TortoiseGit - pull request
有一个仓库,叫Repo A.你如果要往里贡献代码,首先要Fork这个Repo,于是在你的Github账号下有了一个Repo A2,.然后你在这个A2下工作,Commit,push等.然后你希望原始仓库 ...
- 关闭HTC手机充电时屏幕一直亮着绿色电池的办法
首先必须取得ROOT权限,用RE文件管理器进system/bin/把最下面的zchgd文件改名字或者直接删掉重新启动手机充电时就不会亮屏了,电池图标也不会出来,再用数据线连电脑充电吧, ...
- erlang分布式编程模型
erlang分布式编程有两种模型 一.分布式erlang 运行在可信的网络环境中 1.rpc提供的远程过程调用 rpc:call(Node,Mode,Fun,Args) ->Result|{ba ...
- ***C - I love sneakers!(动态规划,分组背包)
C - I love sneakers! Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64 ...
- 一个神奇SQL引发的故障【转】
前几天一个客户数据库主实例告警,诊断过程中发现是由一个慢SQL导致的数据库故障,而在排查逐步深入之后却发现这个现象的不可思议. 问题描述 2016年12日09日,大概9点26分左右,一个客户的生产库主 ...
- 【实验室笔记】C#上位机学习笔记
用C#编写上位机,基本流程是[1]串口配置,[2]串口发送数据,[3]串口接收数据. [1]串口配置 串口的属性配置包括: No.1串口端口号 No.2串口波特率 No.3串口数据位 No.4串口停止 ...
- toggle的使用心得
点击同一个标签可以实现不同效果 或者几个效果 以前一般都是if 判断的 逻辑还有判断比较繁琐 看啦手册后 发现这个功能可以不用判断的自动循环点击事件 比以前的简单好用 主要用法:$("td& ...