题目描述
在生物学中,一些生物的结构是用包含其要素的大写字母序列来表示的。生物学家对于把长的序列分解成较短的序列(即元素)很感兴趣。
如果一个集合 P 中的元素可以串起来(元素可以重复使用)组成一个序列 ss ,那么我们认为序列 ss 可以分解为 P 中的元素。元素不一定要全部出现(如下例中 BBC 就没有出现)。举个例子,序列 ABABACABAAB 可以分解为下面集合中的元素:{A,AB,BA,CA,BBC}
序列 s 的前面 kk 个字符称作 s 中长度为k 的前缀。设计一个程序,输入一个元素集合以及一个大写字母序列 ,设 s’
是序列 s 的最长前缀,使其可以分解为给出的集合 PP 中的元素,求 s’的长度 k。
输入格式
输入数据的开头包括若干个元素组成的集合 O,用连续的以空格分开的字符串表示。字母全部是大写,数据可能不止一行。元素集合结束的标志是一个只包含一个 . 的行,集合中的元素没有重复。
接着是大写字母序列 s ,长度为,用一行或者多行的字符串来表示,每行不超过 76个字符。换行符并不是序列 s 的一部分。
输出格式
只有一行,输出一个整数,表示 S 符合条件的前缀的最大长度。
分析
一道字符串匹配再加上状态转移的题
有若干个字符串元素, 还有一个长的字符串s。
要求在s中,从前往后都能够有相应的子字符串相匹配。
用set集合来存元素,count函数判断是否找的到
dp存状态,前i长度都能匹配,为真
看不太懂我说的,再看看代码应该能懂了。
#include<bits\stdc++.h>
using namespace std;
int dp[200005], m;
//dp前面i长度的子序列都能分解
set<string> s[20];
int main() {
string tp;
while (cin >> tp) {
if (tp == ".") break;
s[tp.size()].insert(tp);
m = max(m, int(tp.size()));
}
int i, ans = 0;
dp[0] = 1;
string n;
n = " ";
while (cin >> tp) {
//可能不止一行 全加上
n = n+tp;
}
for (i = 1; i < n.size(); i++) {
//前面 k 个字符
for (int j = min(i, m); j >= 1; j--) {
string tt = n.substr(i-j+1, j);
//取出从i-j+1位置长度为j的字符串
if (s[tt.size()].count(tt) == 1 && dp[i-j] == 1) {
ans = i;
dp[i] = 1;
break; // j是从大往小走,肯定是最大的
}
}
}
cout << ans;
return 0;
}
(`・ω・´)
structure
n. 结构; 构造; 结构体; (尤指) 建筑物; 精心组织; 周密安排; 体系;
v. 使形成体系; 系统安排; 精心组织;