您的位置:首页 > 其它

USACO:2.3.1 Longest Prefix 最长前缀

2015-11-22 20:13 495 查看


USACO:2.3.1  Longest Prefix 最长前缀

一、题目描述

★Longest Prefix 最长前缀

在生物学中,一些生物的结构是用包含其要素的大写字母序列来表示的.生物学家对于把长的序列

28

分解成较短的(称之为元素的)序列很感兴趣.

如果一个集合 P 中的元素可以通过串联(允许重复;串联,相当于 Pascal 中的 “+” 运算符)

组成一个序列 S ,那么我们认为序列 S 可以分解为 P 中的元素.并不是所有的元素都必须出现.

举个例子,序列 ABABACABAAB 可以分解为下面集合中的元素:

{A, AB, BA, CA, BBC}

序列 S 的前面 K 个字符称作 S 中长度为 K 的前缀.设计一个程序,输入一个元素集合以及一个

大写字母序列,计算这个序列最长的前缀的长度.
PROGRAM NAME: prefix

INPUT FORMAT


输入数据的开头包括 1..200 个元素(长度为 1..10 )组成的集合,用连续的以空格分开的字符串

表示.字母全部是大写,数据可能不止一行.元素集合结束的标志是一个只包含一个 “.” 的行.集

合中的元素没有重复.接着是大写字母序列 S ,长度为 1..200,000 ,用一行或者多行的字符串来表

示,每行不超过 76 个字符.换行符并不是序列 S 的一部分.
SAMPLE INPUT (file prefix.in)

A AB BA CA BBC

ABABACABAABC
OUTPUT FORMAT

只有一行,输出一个整数,表示 S 能够分解成 P 中元素的最长前缀的长度.
SAMPLE OUTPUT (file prefix.out)

11

二、题目解答


简单的动态规划

··设dp[i]表示主串S中前i个字符的子串可得到的最长前缀,dp[L]就是所求。(L为S的长度)状态转移方程:

dp[i]= max{dp[i-1],  dp[i-length(p[j]) + length(p[j])}


源代码

/*
ID:pen_wan1
LANG:C++
TASK:prefix
*/
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;

vector <string> p_set;
string s_seq;
int dp[200000+10];
int max(int a,int b){return a>b? a:b;}

int main()
{
ifstream in("prefix.in");
ofstream out("prefix.out");

for(string s;in>>s&&s!=".";)
p_set.push_back(s);
for(string s;in>>s;)
s_seq=s_seq+s;

dp[0]=0;
for(unsigned int i=1;i<=s_seq.size();i++){//动态规划,背包问题?一定顺序放物品
if(i>0) dp[i]=dp[i-1];
for(int unsigned j=0;j<p_set.size();j++){//元素集合p
string s1=p_set[j];        //遍历集合p中的字符串
unsigned int t1=s1.size(); //元素t1的长度

if(i>=t1&&s_seq.substr(dp[i-s1.size()],s1.size())  ==s1){
//S的子字符串长度大于元素s1的长度,且元素s1是S的后缀
if(i-s1.size()==0||dp[i-s1.size()]!=0)//要么s1就是前缀,要么s1是出现在S的某个前缀后
dp[i]=max(dp[i],dp[i-s1.size()]+s1.size());
}
}
}
out<<dp[s_seq.size()]<< endl;
return 0;
}


由于自身是初学者,编程能力有限,未达到专业程序员的水平,可能误导大家,请大家甄读;文字编辑也一般,文中可能会有措辞不当。博文中的错误和不足敬请读者批评指正。

部分引自  http://pingce.ayyz.cn:9000/usaco/20110129214306/prefix_001.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息