uvalive 3942 Remember the Word (字典树+DP)
2015-09-12 21:35
537 查看
给S个不同的单词和一个长字符串,问将其分解为若干个单词有多少种方法(单词可重复使用)
解法:
设dp[i]表示以i开头的字符串分解的方法数。状态转移方程:dp[i]=sum(dp[i+len(x)]),x为S[i……L]的前缀。
将每一个单词插入到字典树中,然后考虑长字符串S的每一个后缀s[i……L], 看其前缀x是否在字典树中出现,每出现一次,dp[i]累加dp[i+len(x)]即可。
注意总结点数目大小,以及dp的初始化。
解法:
设dp[i]表示以i开头的字符串分解的方法数。状态转移方程:dp[i]=sum(dp[i+len(x)]),x为S[i……L]的前缀。
将每一个单词插入到字典树中,然后考虑长字符串S的每一个后缀s[i……L], 看其前缀x是否在字典树中出现,每出现一次,dp[i]累加dp[i+len(x)]即可。
注意总结点数目大小,以及dp的初始化。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long LL; #define maxn 300005 #define maxm 26 #define mod 20071027 int tree[maxn][maxm],val[maxn],cnt;//Trie树、结点信息、结点数目 int dp[300005]; void init() { cnt=1; memset(tree[0],0,sizeof(tree[0])); memset(dp,0,sizeof(dp)); } inline void Insert(char *s,int v) { int id=0,l=strlen(s); for(int i=0; i<l; ++i) { int c=s[i]-'a'; if(!tree[id][c]) { memset(tree[cnt],0,sizeof(tree[cnt])); tree[id][c]=cnt++; val[cnt]=0; } id=tree[id][c]; } val[id]=v;//字符串的最后一个字符对应结点的附加信息为v } inline void querry(char *s,int l,int pos) { int id=0; for(int i=pos; i<l; ++i) { int c=s[i]-'a'; if(!tree[id][c]) return; id=tree[id][c]; if(val[id]) dp[pos]=(dp[pos]+dp[i+1])%mod; } } char str[300005],w[105]; int main() { int n,ca=1; while(~scanf("%s",str)) { scanf("%d",&n); init(); for(int i=0; i<n; ++i) { scanf("%s",w); Insert(w,1); } int l=strlen(str); dp[l]=1; for(int i=l-1;i>=0;--i) querry(str,l,i); printf("Case %d: %d\n",ca++,dp[0]); } return 0; }
相关文章推荐
- [锋利的JQ]-超链接提示效果
- Windows7系统下JAVA运行环境下载、安装和设置
- 国内投行的工资
- 程序员必须知道的10大基础实用算法及其讲解
- iterator_traits 存在的作用与意义
- iperf网络性能测试
- idea 使用maven构建项目
- 国内投行的工资
- /bin/bash^M: bad interpreter: 没有那个文件或目录
- alsa设置默认声卡
- ADB简述
- codeforces 159D D. Palindrome pairs( manacher+dp )
- 使用EDMX查询(EF基础系列10)
- android获取asset文件存到SD卡
- Java位运算
- 南京大学行业求职研究报告——投资银行篇
- wxWidgets
- Linux下安装运行keil uVision 4 (MDK v4.7)
- HDU_3572_Task Schedule(最大流)
- 2016百度的三个编程题