USACO-Section2.3 prefix[DP]

来源:互联网 发布:查询python版本 编辑:程序博客网 时间:2024/05/15 23:52

题目大意:

如果一个集合 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;}
原创粉丝点击