USACO-Section2.3 prefix[DP]

题目大意:

如果一个集合 P 中的元素可以通过串联,组成一个序列 S,那么我们认为序列 S 可以分解为 P 中的元素。元素不一定要全部出现(如下例中BBC就没有出现)。举个例子,序列 ABABACABAAB 可以分解为下面集合中的元素:
{A, AB, BA, CA, BBC}
序列 S 的前面 K 个字符称作 S 中长度为 K 的前缀。设计一个程序,输入一个元素集合以及一个大写字母序列 S ,设S’是序列S的最长前缀,使其可以分解为给出的集合P中的元素,求S’的长度K。

样例输入:

A AB BA CA BBC
.
ABABACABAABC

样例输出:

11

题解:

用了动态规划的思想,从后向前去找;
dp[i] 表示 从第i位开始的最长前缀的长度;
dp[i]=max(dp[i+len[j]]+len[j],dp[i])
上式看代码。<(  ̄^ ̄)(θ(θ☆( >_<

C++
/*
ID:mujinui1 
LANG:C++
TASK:prefix
*/
#include<fstream>
#include<string>
#include<algorithm>
#include<cstring>
using namespace std;
ifstream fin("prefix.in");
ofstream fout("prefix.out");
string target,flag;   
 //target  目标序列      flag  读入的时候用到 
int len_target;         //target长度 
int len[205],dp[200005];  
string s[205];      //len[i] 是  s[i]的 长度 
int t=0;   //元素的个数 

int main(){
    memset(dp,0,sizeof(dp));

    //read 
    while(fin>>flag){
        if(flag=="."){
            break;
        }
        else{
            s[t]=flag;
            len[t++]=flag.length();
        }
    }
    fin>>target;
    while(fin>>flag){
        target+=flag;
    }
    len_target=target.length();

    for(int i=len_target;i>=0;i--){      
    //这一步意义不大,脑子不用拐弯而已.. 
        target[i+1]=target[i];
    }


    for(int i=len_target;i>=1;i--){ 
                 //t 个元素都遍历一遍 
            if(len_target-i+1>=len[j]){
                bool test=true;
                for(int k=0;k<len[j];k++){
                    if(target[i+k]!=s[j][k]){
                      test=false;
                      break;  
                    }
                }
                //不同就不用做比较 
                if(test==true){
                   dp[i]=max(dp[i+len[j]]+len[j],dp[i]);
                }
           }
        }
    }
    fout<<dp[1]<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值