[PAT甲级]1045 Favorite Color Stripe 详细讲解+AC代码

[PAT甲级]1045 Favorite Color Stripe


以下所述均为个人理解,如有错误,还望指正


题目

Eva is trying to make her own color stripe out of a given one. She would like to keep only her favorite colors in her favorite order by cutting off those unwanted pieces and sewing the remaining parts together to form her favorite color stripe.

It is said that a normal human eye can distinguish about less than 200 different colors, so Eva's favorite colors are limited. However the original stripe could be very long, and Eva would like to have the remaining favorite stripe with the maximum length. So she needs your help to find her the best result.

Note that the solution might not be unique, but you only have to tell her the maximum length. For example, given a stripe of colors {2 2 4 1 5 5 6 3 1 1 5 6}. If Eva's favorite colors are given in her favorite order as {2 3 1 5 6}, then she has 4 possible best solutions {2 2 1 1 1 5 6}, {2 2 1 5 5 5 6}, {2 2 1 5 5 6 6}, and {2 2 3 1 1 5 6}.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer NNN (≤200\le 200200) which is the total number of colors involved (and hence the colors are numbered from 1 to NNN). Then the next line starts with a positive integer MMM (≤200\le 200200) followed by MMM Eva's favorite color numbers given in her favorite order. Finally the third line starts with a positive integer LLL (≤104\le 10^4104) which is the length of the given stripe, followed by LLL colors on the stripe. All the numbers in a line a separated by a space.

Output Specification:

For each test case, simply print in a line the maximum length of Eva's favorite stripe.


注意 :

最长公共子串(Longest Common Substirng)和最长公共子序列(Longest Common Subsequence,简称LCS)的区别为是最长公共子串的串是一个连续的部分,而最长公共子序列则是从不改变序列的顺序,而从序列中去掉任意的元素而获得新的序列;通俗的说就是子串中字符的位置必须是连续的而子序列则可以不必连续.

题解:动态规划

1. 确定表达式含义:dp[i][j]表示字符串x[1…i]与y[1…j]之间最长公共子序列的长度.

2. 确定关系式:最长公共子序列的长度需要判断当前位置x[i]与y[j]是否相同,如果相同,则其长度等于其前缀的长度+1,在此题中,
dp[i][j] = x[i]==y[j]?dp[i][j-1]+1:max(dp[i-1][j],dp[i][j-1]),
不同于普通的LCS关系式:
dp[i][j]=x[i]==y[j]?dp[i-1][j-1]+1:max(dp[i-1][j],dp[i][j-1]),这是因为在此题中,x[i]中的元素可以按顺序重复出现.
对于本题来说:
如果当前有x[i]==y[j],仍需要判断y[j]前面的元素y[j-1]是否与x[i]相等,所以,此时相当于在最大公共子串中同时保留y[j]与y[j-1],在表达式中具体要怎么体现呢?
既然我现在不是根据dp[i-1][j-1]来判断,而是还要考虑之前有没有重复元素出现,而dp[i][j-1]表示前一个x[1…i]与y[1…j-1]的最长公共子序列
假设x[i]==y[j-1],此时不就是上述的重复出现的结果吗,所以dp[i][j] = x[i]==y[j]?dp[i][j-1]+1:();而如果当前x[i]!=y[j],那当然就不存在判断重复的情况.

dp[i][j] = x[i]==y[j]?dp[i][j-1]+1:max(dp[i-1][j],dp[i][j-1])

3. 确定边界,dp[i][0]=dp[0][j]=0;

#include<bits/stdc++.h>
using namespace std;
int dp[210][10010];
int main()
{
   int x[210];
   int y[10010];
   int color_nums;
   int x_nums;
   int  y_nums;
   cin>>color_nums;
   cin>>x_nums;
   for(int i=1;i<=x_nums;i++)
   {
    cin>>x[i];
    dp[i][0]=0;
   }
   cin>>y_nums;
   for(int i=1;i<=y_nums;i++)
   {
    cin>>y[i];
    dp[0][i]=0;
   }
   dp[0][0]=0;
   for(int i=1;i<=x_nums;i++)
   {
    for(int j=1;j<=y_nums;j++)
    {
        if(x[i]==y[j])
        {
            dp[i][j]=dp[i][j-1]+1;
        }
        else
        {
           dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
        }
    }
   }
   cout<<dp[x_nums][y_nums];
}

AC结果:
在这里插入图片描述


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值