【USACO Open11】forgot
阿新 • • 發佈:2018-12-15
題目描述
發生了這麼多,貝茜已經忘記了她 cowtube 密碼。然而,她記得一些有用的資訊。首先,她記得她的密碼(記為變數 )長度為 字串,並可以被分成 一個或多個詞(不一定是唯一的),詞來自於字典中 個獨特的詞。 一個詞 ,被定義為一個長度 的小寫字母序列(‘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;
}