卧薪尝胆,厚积薄发。
SHOI2005 带限制的最长公共子序列
Date: Mon Sep 03 17:42:12 CST 2018
In Category:
NoCategory
Description:
给三个字符串
$A,B,C$
,求
$A,B$
的最长公共子序列,满足
$C$
是这个子序列的子序列。
$1\le len \le 500$
Solution:
记
$f[i][j][k]$
表示三个字符串分别到了
$i,j,k$
位置,初值是
$A$
和
$B$
的
$LCS$
数组,然后转移只是比普通
$LCS$
多加了一个
$C$
的转移,即如果加了新字符刚好和
$C[k]$
相同,那么
$C$
也可以有上一个转移过来,注意由于强制
$C$
跑满,所以
$k>0$
的状态初值都要赋成
$-INF$
。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define MAXL 510
char a[MAXL],b[MAXL],c[MAXL];
int la,lb,lc;
int f[MAXL][MAXL][2];
#define NEG 0xc0c0c0c0
int main()
{
scanf("%s%s%s",a + 1,b + 1,c + 1);
la = strlen(a + 1);lb = strlen(b + 1);lc = strlen(c + 1);
int cur = 0;
for(int i = 1;i <= la;++i)
{
for(int j = 1;j <= lb;++j)
{
f[i][j][cur] = max(f[i - 1][j][cur],f[i][j - 1][cur]);
if(a[i] == b[j])f[i][j][cur] = max(f[i][j][cur],f[i - 1][j - 1][cur] + 1);
}
}
for(int k = 1;k <= lc;++k)
{
cur = cur ^ 1;
for(int i = 0;i <= la;++i)
for(int j = 0;j <= lb;++j)
f[i][j][cur] = NEG;
for(int i = 1;i <= la;++i)
{
for(int j = 1;j <= lb;++j)
{
if(a[i] == b[j])
{
f[i][j][cur] = max(f[i][j][cur],f[i - 1][j - 1][cur] + 1);
if(a[i] == c[k])
{
f[i][j][cur] = max(f[i][j][cur],f[i - 1][j - 1][cur ^ 1] + 1);
}
}
f[i][j][cur] = max(f[i][j][cur],max(f[i - 1][j][cur],f[i][j - 1][cur]));
}
}
}
if(f[la][lb][cur] > 0)cout << f[la][lb][cur] << endl;
else puts("NO SOLUTION");
return 0;
}
In tag:
DP-LCS
Copyright © 2020
wjh15101051
ღゝ◡╹)ノ♡