LA3942 Remember the Word
2024-10-09 02:51:33
题目链接:https://vjudge.net/problem/UVALive-3942
本篇是刘汝佳《算法竞赛入门经典——训练指南》的读书笔记(复述),详见原书 \(P209\) .
解题思路:
先用字典树维护字典中所有的单词。
定义 \(f(x)\) 为以长字符串中第 \(x\) 个字符开始的字符串的分解方案数,则 \(f(x) = sum{f(x+len(i))}\) ,其中 \(i\) 是该字符串的所有前缀。
用一种类似 \(DFS\) 的方式解决这个问题。
注意:书中的模数写错了。
AC代码:
#include <bits/stdc++.h> using namespace std;
typedef long long ll;
const ll mod = ;
const int maxn = +;
char inp[maxn];
struct Trie{
int ch[][];
int val[];
int sz;
void inserts(char *s,int v){
int u=,n=strlen(s);
for(int i=;i<n;i++){
int c=s[i]-'a';
if(!ch[u][c]){
memset(ch[sz],,sizeof(ch[sz]));
val[sz]=;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]=v;
}
};
Trie tree;
ll f[maxn]; ll solve(int head,int tail){
if(f[head]!=-) return f[head];
int now=;
ll ret=;
for(int i=head;i<tail;i++){
int c=inp[i]-'a';
int Next=tree.ch[now][c];
if(Next==){
f[head]=ret;
return ret;
}
if(tree.val[Next])
ret=(ret+solve(i+,tail))%mod;
now=Next;
}
f[head]=ret;
return ret;
}
int main(){
char word[];
int kase=;
while(scanf("%s",inp)==){
int S;
memset(f,-,sizeof(f));
tree.sz=;
memset(tree.ch[],,sizeof(tree.ch[]));
scanf("%d",&S);
while(S--){
scanf("%s",word);
tree.inserts(word,);
}
int tail=strlen(inp);
f[tail]=;
printf("Case %d: %lld\n",kase++,solve(,tail));
}
return ;
}
最新文章
- 《饥荒游戏》SW BUG 刷猴子 &; 刷淘气值 办法
- XOR Swap
- Dynamic CRM 2013学习笔记(四十五)修改实体及字段的前缀(不用new_开头)
- Asp.Net 三层架构之泛型应用
- ViewConfiguration.getScaledTouchSlop () 用法
- asp.net控件开发基础(1)(转)原文更多内容
- Java基础(60):Java打包生成Jar和Javadoc说明文档,以及在另外的工程中导入和使用自己的Jar
- N年后给自己一些忠诚的建议
- POJ 2955 Brackets 区间合并
- bzoj 2285 [Sdoi2011]保密(二分,spfa + 最大流)
- Redundant Call to Object.ToString()
- iOS navigationBar导航栏底部与self.view的分界线的隐藏
- Hadoop的基本命令【转载】
- 【每日一摩斯】-Troubleshooting: High CPU Utilization (164768.1) - 系列4
- 自定义MVP .net框架
- VS2010 c/c++ 本地化 emscripten 配置
- 基于 HTML5 WebGL 的 3D SCADA 主站系统
- ios 添加三方字体
- Pycharm 安装 idea VIM
- Android开发中遇到的问题(一)——Android模拟器端口被占用问题的解决办法