USACO:2.3.1 Longest Prefix 最长前缀

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


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值