【题】【DP(trie维护)】NKOJ3824 解密游戏
来源:互联网 发布:发票软件怎么安装 编辑:程序博客网 时间:2024/05/07 19:50
NKOJ3824 解密游戏
时间限制 : - MS 空间限制 : 465536 KB
评测说明 : 2000ms
问题描述
小南和小开特别喜欢玩解密游戏,轮到小南加密的时候,由于他的加密方式过于丧心病 狂,所以小开怎么也不能解密成功,于是她来找你帮忙。 密文是一个长度为 n 的数字串,只由 0~9 之间的数字组成。每个小写字母对应 0~9 之 间的一个数字。小南和小开共同拥有一本字典,字典中有 m 个单词,每个单词长度不超过 50。 明文是一个数字,表示最少用多少个单词首尾拼接在一起,使得拼接而成的这个字符串 可以表示密文(也即相同位置的字符串中字母对应数字跟密文相同)。单词可以重复使用。
输出明文,如果无解的话明文为-1。
输入格式
第一行两个正整数 n,m。
第二行有 26 个数字,每个数字是 0~9 之间的数,分别表示字母 a~z 对应的数字。
第三行是长度为 n 的数字串,表示密文。 接下来 m 行,每行一个小写字母串,表示字典中的一个单词。
输出格式
输出一个整数,表示明文
样例输入 1
10 5
2 2 2 3 3 3 4 4 1 1 5 5 6 6 0 7 0 7 7 8 8 8 9 9 9 0 7325189087
it
your
reality
real
our
样例输出 1
2
样例输入 2
10 5
2 2 2 3 3 3 4 4 1 1 5 5 6 6 0 7 0 7 7 8 8 8 9 9 9 0 4294967296
it
your
reality
real
our
样例输出 2
-1
提示
【数据范围】
对于 30%的数据:1 ≤ n,m ≤ 1000。
对于 100%的数据:1 ≤ n,m ≤ 105。
【样例 1 解释】
我们最少可以用两个单词 reality our,组成的字符串 realityour 去表示密文。
【样例 2 解释】
没有选法使得单词组成的字符串可以表示密文。
来源 wjj
思路:
先全转为数字串。
状态:f[i]表示匹配前i位,且i为结尾的最小子串数。
考虑在密文中依次讨论每一位,从该位出发,往后x位若存在一个子串与题目所给单词匹配则,f[i+x]=min(f[i+x],f[i]+1)
使用字典树存储子串
#include<cstdio>#include<cstring>#include<vector>#include<iostream>using namespace std;const int lenmax=1006;const int inf=1e9;int n,m;int c[27];char b[lenmax],a[lenmax];//...............................................struct trie{ int ne[10],len; trie(int d=0,int e=0) { len =e; for(int i=0;i<=9;i++) ne[i]=d; }};#define add push_back(trie())int now=0;vector<trie> w(1,trie());void insert(int len){ int p=0,t; for(int i=0;i<len;i++) { t=c[a[i]-'a']; if(w[p].ne[t]!=0) p=w[p].ne[t]; else { w.add; now++; p=w[p].ne[t]=now; } } w[p].len=len;}//...............................................int dp[lenmax];int* f;void dosomething(int k){ int p=0,t; for(int i=k+1;i<n;i++) { t=b[i]-'0'; p=w[p].ne[t]; if(p==0) break; if(w[p].len!=0) { if(k+w[p].len<n) f[k+w[p].len]=min(f[k+w[p].len],f[k]+1); else return ; } }}//...............................................int main(){ scanf("%d%d",&n,&m); for(int i=0;i<26;i++) scanf("%d",c+i); scanf("%s",b); for(int i=1;i<=m;i++) { scanf("%s",a); insert(strlen(a)); } f=dp+1; f[-1]=0; for(int i=0;i<n;i++) f[i]=inf; for(int i=0;i<n;i++) { if(f[i-1]==inf) continue; dosomething(i-1); } cout<<(f[n-1]==inf ? -1 : f[n-1]);}
- 【题】【DP(trie维护)】NKOJ3824 解密游戏
- NOIP2017复习 解密游戏(trie+dp)
- (2017夏令营CONTEST4) NKOJ 3824 解密游戏(trie,dp)
- trie+dp
- SCU2016-03 A题 trie树 + dp
- 重庆市四校联考(南开出题) 解密游戏(Trie树 | | 动态规划)
- uva 1401 dp+Trie
- LA3942 Trie+DP
- 1213 trie+DP
- uvalive 3942(dp + trie)
- UVA1401&LA3942 Trie+DP
- LA3942 trie+dp
- SCU2016-05 I题 trie图 + 大数dp
- hdu 5845 Best Division(trie+dp,好题)
- hdu4570Multi-bit Trie (区间DP)
- Uva1401 Trie树 + 简单dp
- dp+trie nbut1222 English Game
- UVALive 3942 Trie加速dp
- SQL truncate 、delete与drop区别
- Java通过异常处理错误
- python数据分析集成开发环境
- AirBnb 创业三剑客
- u3d 批量设置预设
- 【题】【DP(trie维护)】NKOJ3824 解密游戏
- 今天作为一个新的起点
- 1、csv基础
- 静态库动态库
- java构造器内部的多态方法
- jquery.form.js IE下异步提交文件的问题解决办法
- 装饰模式与代理模式的区别
- Java类型信息:RTTI
- cocos creator 调用原生端方法