P1470 [USACO2.3]最长前缀 Longest Prefix

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

如果一个集合 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. 使形成体系; 系统安排; 精心组织;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值