您的位置:首页 > 其它

USACO-Section 2.3 Longest Prefix (DP)

2016-01-27 17:14 246 查看


描述

在生物学中,一些生物的结构是用包含其要素的大写字母序列来表示的。生物学家对于把长的序列分解成较短的序列(即元素)很感兴趣。

如果一个集合 P 中的元素可以通过串联(元素可以重复使用,相当于 Pascal 中的 “+” 运算符)组成一个序列 S ,那么我们认为序列 S 可以分解为 P 中的元素。元素不一定要全部出现(如下例中BBC就没有出现)。举个例子,序列 ABABACABAAB 可以分解为下面集合中的元素:

{A, AB, BA, CA, BBC}

序列 S 的前面 K 个字符称作 S 中长度为 K 的前缀。设计一个程序,输入一个元素集合以及一个大写字母序列 S ,设S'是序列S的最长前缀,使其可以分解为给出的集合P中的元素,求S'的长度K。


格式

PROGRAM NAME: prefix

INPUT FORMAT:

(file prefix.in)

输入数据的开头包括 1..200 个元素(长度为 1..10 )组成的集合,用连续的以空格分开的字符串表示。字母全部是大写,数据可能不止一行。元素集合结束的标志是一个只包含一个 “.” 的行。集合中的元素没有重复。接着是大写字母序列 S ,长度为 1..200,000 ,用一行或者多行的字符串来表示,每行不超过 76 个字符。换行符并不是序列 S 的一部分。

OUTPUT FORMAT:

(file prefix.out)

只有一行,输出一个整数,表示 S 符合条件的前缀的最大长度。


SAMPLE INPUT

A AB BA CA BBC
.
ABABACABAABC


SAMPLE OUTPUT

11


第一反应是dfs,但复杂度太高,估计会超时

又想到可以对于每一个合法位置,可以通过集合内的字符串往后扩展,如果扩展成功则将更新答案最大值

/*
ID: your_id_here
PROG: prefix
LANG: C++
*/
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

int cnt=0,ans=0,i=0,len,j,k;
char s[200015]={0},tmp[77];
bool dp[200015]={false};

struct Node {
char s[11];
int len;
}pri[205];

bool mycmp() {
for(k=0;k<pri[j].len;++k)
if(s[i+k+1]!=pri[j].s[k])
return false;
return true;
}

int main() {
freopen("prefix.in","r",stdin);
freopen("prefix.out","w",stdout);
while(scanf("%s",pri[cnt].s),pri[cnt].s[0]!='.') {
pri[cnt].len=strlen(pri[cnt].s);
++cnt;
}
while(1==scanf("%s",tmp)) {//s串可以分成多行
strcpy(s+1+len,tmp);
len+=strlen(tmp);
}
dp[0]=true;
while(i<=ans&&i<=len) {
if(dp[i])
for(j=0;j<cnt;++j)
if(!dp[i+pri[j].len]&&mycmp()) {
dp[i+pri[j].len]=true;
ans=max(ans,i+pri[j].len);
}
++i;
}
printf("%d\n",min(len,ans));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: