【USACO Open11】forgot

题目描述

发生了这么多,贝茜已经忘记了她 cowtube 密码。然而,她记得一些有用的信息。首先,她记得她的密码(记为变量 P P P)长度为 L ( 1 ≤ L ≤ 1 , 000 ) L(1\le L\le 1,000) L(1L1,000) 字符串,并可以被分成 一个或多个词(不一定是唯一的),词来自于字典中 N W ( 1 ≤ N W ≤ 1 , 000 ) NW(1\le NW\le 1,000) NW(1NW1,000) 个独特的词。 一个词 W i W_i Wi,被定义为一个长度 1 … 20 1\dots 20 120 的小写字母序列(‘a’…‘z’)。她还记得她密码中某些字母的位置。
请看下面的例子。
贝西知道她的密码看起来像"a??l?ban???"(’?'代表一个字母,她不记得), 她的字典里有下面的词:
apple
cow
farmer
banana
bananas
pies
贝西有两个密码是可能的“applebananapies”和“applebananascow”。
给你字典,贝西记得的字母,请找到她的密码。如果有一个以上的密码是可能的,找到字典序最前的。

算法分析

枚举每个位置和以该位置为结尾的字符串,跑背包 DP 即可,实现时可以使用 C++ STL 库中的 string,更方便地实现字符串相加和比较字典序操作,注意转移前要判断前一状态是否可行。

代码实现

#include <cstdio>
#include <cstring>
#include <string>
char s[1005],sin[1005];int len[1005];
std::string dic[1005],f[1005];
inline bool check(int x,int y) {
	for(int i=0;i<len[y];++i) {
		if(s[x-i]!=dic[y][len[y]-1-i]&&s[x-i]!='?') return false;
	}
	return true;
}
int main() {
	int l,nw;scanf("%d%d",&l,&nw);
	scanf("%s",s+1);
	for(int i=0;i<nw;++i) {
		scanf("%s",sin);
		len[i]=strlen(sin);
		dic[i]=sin;
	}
	for(int i=1;i<=l;++i) {
		for(int j=0;j<nw;++j) {
			if(i-len[j]>=0&&check(i,j)) {
				if(i-len[j]==0||!f[i-len[j]].empty())
					if(f[i].empty()||f[i]>f[i-len[j]]+dic[j])
						f[i]=f[i-len[j]]+dic[j];
			}
		}
	}
	printf("%s\n",f[l].c_str());
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值