bzoj3304[Shoi2005]带限制的最长公共子序列 DP

题意:给出三个序列,求出前两个的公共子序列,且包含第三个序列,要求长度最长。

这道题目怎么做呢,f[i][j]表示a串1-i,b串1-j的最长,g[i][j]表示a串i-n,b串j-m最长,

那么只需要判断中间有没有包好c串就OK了,这样都是O(n^2)的。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
#define pa pair<int,int>
#define ll long long
#define N 3008
#define mx 1e9
using namespace std;
int sc()
{
    int i=0,f=1; char c=getchar();
    while(c>‘9‘||c<‘0‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘)i=i*10+c-‘0‘,c=getchar();
    return i*f;
}
int fa[N],fb[N];
int f[N][N],g[N][N];
int a[N],b[N],c[N];
int La,Lb,Lc,ans;
int main()
{
    La=sc();for(int i=1;i<=La;i++)a[i]=sc();
    Lb=sc();for(int i=1;i<=Lb;i++)b[i]=sc();
    Lc=sc();for(int i=1;i<=Lc;i++)c[i]=sc();
    for(int i=1;i<=La;i++)
        for(int j=1;j<=Lb;j++)
            if(a[i]==b[j])
                f[i][j]=f[i-1][j-1]+1;
            else
                f[i][j]=max(f[i][j-1],f[i-1][j]);
    if(!Lc)
    {
        printf("%d\n",f[La][Lb]);
        return 0;
    }
    for(int i=La;i>=1;i--)
        for(int j=Lb;j>=1;j--)
            if(a[i]==b[j])
                g[i][j]=g[i+1][j+1]+1;
            else
                g[i][j]=max(g[i][j+1],g[i+1][j]);
    for(int i=1;i<=La;i++)
        if(i>1&&a[i-1]!=c[1])fa[i]=fa[i-1];
        else for(int j=1,k=i;k<=La;k++)
        {
            if(a[k]==c[j])j++;
            if(j>Lc){fa[i]=k;break;}
        }
    for(int i=1;i<=Lb;i++)
        if(i>1&&b[i-1]!=c[1])fb[i]=fb[i-1];
        else for(int j=1,k=i;k<=Lb;k++)
        {
            if(b[k]==c[j])j++;
            if(j>Lc){fb[i]=k;break;}
        }
    for(int i=1;i<=La;i++)
        if(fa[i])
        for(int j=1;j<=Lb;j++)
            if(fb[j])
                ans=max(ans,f[i-1][j-1]+g[fa[i]+1][fb[j]+1]);
    ans?cout<<ans+Lc:cout<<-1;
}

  

时间: 2024-10-10 16:57:52

bzoj3304[Shoi2005]带限制的最长公共子序列 DP的相关文章

hdu 1159 Common Subsequence(最长公共子序列 DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1159 Common Subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 25416    Accepted Submission(s): 11276 Problem Description A subsequence of

hdu 1159 common sequence (最长公共子序列 dp)

http://acm.hdu.edu.cn/showproblem.php?pid=1159 题意 : 给出两个字符串 求出最长公共子序列 思路: if(str1[i]==str2[j]) { dp[i][j]=max(dp[i-1][j-1]+1,max(dp[i-1][j],dp[i][j-1])); } else dp[i][j]=max(dp[i-1][j],dp[i][j-1]); #include<cstdio> #include<cstring> #include&l

lcs(最长公共子序列),dp

lcs(最长公共子序列) 求两个序列的lcs的长度,子序列可不连续 dp[i][j]=dp[i-1][j-1]+1(a[i]==b[i]) dp[i][j]=max(dp[i-1][j],dp[i][j-1])(a[i]!=b[i]) memset(dp,0,sizeof(dp)); for(int i=1;i<=n1;i++){ for(int j=1;j<=n2;j++){ if(a[i]==b[j]) dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=max(

最长公共子序列 DP

算法老师的作业,一道dp基础题,给你两个序列,问你最长公共子序列是什么,比如:(a,b)是(a,c,d,b)的子序列.注意不是最长公共子串,这里的子序列可以不连续. 两个for循环就出来了,每一个dp[i][j]可以从dp[i-1][j-1].dp[i-1][j].dp[i][j-1]三种情况更新过来,取个最大的,然后把路径用123存下来,最后再顺着路径找然后逆序输出就行. sample input: 7 4 A B C B D A B B C D B 7 6 A B C B D A B B D

求最长公共子序列-DP问题

Longest common subsequence problem The longest common subsequence (LCS) problem is the problem of finding the longest subsequence common to all sequences in a set of sequences (often just two sequences). It differs from the longest common substring p

[BZOJ2423][HAOI2010]最长公共子序列

试题描述 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序列<i0,i1,…,ik-1>,使得对所有的j=0,1,…,k-1,有xij = yj.例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列.对给定的两个字符序列,求出他们最长的公共子序列长度,以及最长公共子序列个数. 输入 第1行为第1个字

动态规划之最长公共子序列(LCS)

         在字符串S中按照其先后顺序依次取出若干个字符,并讲它们排列成一个新的字符串,这个字符串就被称为原字符串的子串          有两个字符串S1和S2,求一个最长公共子串,即求字符串S3,它同时为S1和S2的子串,且要求它的长度最长,就是这里的 最长公共子序列问题.           最长公共子序列问题的递推条件如下:dp[i][j]表示s1前i个字符组成的前缀子串与s2前j个字符组成的前缀子串的最长公共子序列           dp[0][ j ]( 0<=j<=m)

hdu1243 dp (类最长公共子序列)

题意:射击演习中,已知敌人出现的种类顺序,以及自己的子弹种类顺序,当同种类的子弹打到同种类的敌人时会得到相应分数,问最多能得多少分. 这题的题意很好理解,而且模型也很常见,是带权值的类最长公共子序列问题.但是我 WA 了四发```第一发,t 定义了两次,并执意要从下标 1 开始读(这个貌似没问题的).第二次是改了之后 dp 数组的转移方程没有写对.第三 WA 是改了转移方程还是没有改对Orz ,第四 WA 是```我的内心几乎是崩溃的,恩,还是没有改对…… 1 #include<stdio.h>

最长公共子序列及其引申问题

最长公共子序列是经典的动态规划问题,在很多书籍和文章中都有介绍,这里对这一经典算法进行回顾并对两个follow up questions进行总结和分析. 1. 回顾LCS(longest common subsequence)解法,求LCS长度 典型的双序列动态规划问题,dp[i][j]表示第一个序列前i项与第二个序列的前j项.... 所以对应此题,dp[i][j]表示序列s1的前i项与序列s2的前j项的最长公共子序列. 得到如下递推关系式: dp[i][j] = dp[i - 1][j - 1