---------------------------------------------------------------------------------
Longest Prefix
IOI'96
The structure of some biological objects is represented by the sequence of their constituents denoted by uppercase letters. Biologists are interested in decomposing a long sequence into shorter ones called primitives.
We say that a sequence S can be composed from a given set of primitives P if there is a some sequence of (possibly repeated) primitives from the set whose concatenation equals S. Not necessarily all primitives need be present. For instance the sequence ABABACABAABcan be composed from the set of primitives
{A, AB, BA, CA, BBC}
The first K characters of S are the prefix of S with length K. Write a program which accepts as input a set of primitives and a sequence of constituents and then computes the length of the longest prefix that can be composed from primitives.
PROGRAM NAME: prefix
INPUT FORMAT
First, the input file contains the list (length 1..200) of primitives (length 1..10) expressed as a series of space-separated strings of upper-case characters on one or more lines. The list of primitives is terminated by a line that contains nothing more than a period (`.'). No primitive appears twice in the list. Then, the input file contains a sequence S (length 1..200,000) expressed as one or more lines, none of which exceed 76 letters in length. The "newlines" are not part of the string S.
SAMPLE INPUT (file prefix.in)
A AB BA CA BBC
.
ABABACABAABC
OUTPUT FORMAT
A single line containing an integer that is the length of the longest prefix that can be composed from the set P.
SAMPLE OUTPUT (file prefix.out)
11
描述
在生物学中,一些生物的结构是用包含其要素的大写字母序列来表示的。生物学家对于把长的序列分解成较短的(称之为元素的)序列很感兴趣。
如果一个集合 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 的一部分。
OUTPUT FORMAT
只有一行,输出一个整数,表示 S 能够分解成 P 中元素的最长前缀的长度。
SAMPLE INPUT (file prefix.in)
A AB BA CA BBC
.
ABABACABAABC
SAMPLE OUTPUT (file prefix.out)
11
============================ 华丽的分割线 ============================
dp的思路:转换方程dp[i] = dp[i - j] + j
我的思路: dp[i] 表示前i个字母组成的prefix是否可以被primitive组成,1表示可以,0表示不行;当满足以下条件时,说明dp[i]可以置1 —— dp[i-j] 为1,prefix最后的j个字幕组成的string属于primitive。
注意循环开始前要设置dp[0] = 1
/*
ID: wangxin12
PROG: prefix
LANG: C++
*/
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
vector<string> primitive;
string sequence = "";
int dp[200001] = { 1 };
int ansMax = 0;
int main() {
ifstream fin("prefix.in");
ofstream fout("prefix.out");
int i, j, k;
//read data
string temp = "";
fin>>temp;
while(temp != ".") {
primitive.push_back(temp);
fin>>temp;
}
while(fin>>temp) {
sequence += temp;
}
//body
for(i = 1; i <= sequence.size(); i++) {
for(j = 1; j <= i && j <= 10; j++) {
for(k = 0; k < primitive.size(); k++) {
if( primitive[k].length() == j
&& primitive[k] == sequence.substr(i - j, j)
&& dp[i - j] > 0 )
dp[i] = 1;
}
}
}
for(k = sequence.size(); k >= 0; k--) {
if(dp[k] > 0) break;
}
fout<<k<<endl;
//output
fin.close();
fout.close();
return 0;
}