借鉴了这位大佬的代码思路
题意 是,给你三个串
a
,
b
,
v
i
r
u
s
a,b,virus
a , b , v i r u s 问你能找到的
a
,
b
a,b
a , b 的最长不包含所给的
v
i
r
u
s
virus
v i r u s 串的公共子序列是啥,输出。 思路 最长公共子序列,直接套用LCS就行。这题不同的是要再加一个维度,代表
a
,
b
a,b
a , b 的公共子序列中能够与virus配对的最长前缀长度为k,即
d
p
[
i
]
[
j
]
[
k
]
dp[i][j][k]
d p [ i ] [ j ] [ k ] ,最后只要在
d
p
[
n
]
[
m
]
[
k
]
,
0
<
=
k
<
t
dp[n][m][k],0<=k<t
d p [ n ] [ m ] [ k ] , 0 < = k < t (
n
n
n 是
a
a
a 串的长度,
m
m
m 是
b
b
b 串的长度中,
t
t
t 是
v
i
r
u
s
virus
v i r u s 串的长度)找到一个最大值,然后定义一个四维数组保存最长公共子序列的路径即可。具体看代码。 代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn= 100 + 10 ;
int dp[ maxn] [ maxn] [ maxn] , pre[ maxn] [ maxn] [ maxn] [ 3 ] ;
char s1[ maxn] , s2[ maxn] , vir[ maxn] ;
char ans[ maxn] ;
int nxt[ maxn] ;
int n, m, t;
inline void getm ( int x, int y, int z, int x1, int y1, int z1, int v)
{
if ( dp[ x1] [ y1] [ z1] + v> dp[ x] [ y] [ z] )
{
dp[ x] [ y] [ z] = dp[ x1] [ y1] [ z1] + v;
pre[ x] [ y] [ z] [ 0 ] = x1;
pre[ x] [ y] [ z] [ 1 ] = y1;
pre[ x] [ y] [ z] [ 2 ] = z1;
}
}
void get_next ( )
{
nxt[ 0 ] = nxt[ 1 ] = 0 ;
for ( int i= 1 ; i< t; ++ i)
{
int j= nxt[ i] ;
while ( j> 0 && vir[ i] != vir[ j] ) j= nxt[ j] ;
if ( vir[ i] == vir[ j] ) j++ ;
nxt[ i+ 1 ] = j;
}
}
int main ( )
{
scanf ( "%s" , s1) ;
scanf ( "%s" , s2) ;
scanf ( "%s" , vir) ;
n= strlen ( s1) ;
m= strlen ( s2) ;
t= strlen ( vir) ;
get_next ( ) ;
memset ( dp, 0xff , sizeof ( dp) ) ;
memset ( pre, 0xff , sizeof ( pre) ) ;
dp[ 0 ] [ 0 ] [ 0 ] = 0 ;
for ( int i= 0 ; i<= n; ++ i)
for ( int j= 0 ; j<= m; ++ j)
for ( int k= 0 ; k< t; ++ k)
{
getm ( i+ 1 , j, k, i, j, k, 0 ) ;
getm ( i, j+ 1 , k, i, j, k, 0 ) ;
if ( dp[ i] [ j] [ k] >= 0 && s1[ i] == s2[ j] )
{
if ( s1[ i] == vir[ k] )
{
getm ( i+ 1 , j+ 1 , k+ 1 , i, j, k, 1 ) ;
}
else
{
int p= nxt[ k] ;
while ( p> 0 && s1[ i] != vir[ p] ) p= nxt[ p] ;
getm ( i+ 1 , j+ 1 , p+ ( s1[ i] == vir[ p] ) , i, j, k, 1 ) ;
}
}
}
int x, y, z, maxv= - 1 ;
for ( int k= 0 ; k< t; ++ k)
if ( dp[ n] [ m] [ k] > maxv)
{
maxv= dp[ n] [ m] [ k] ;
z= k;
}
if ( maxv<= 0 ) printf ( "0\n" ) ;
else
{
x= n; y= m;
int len= maxv;
while ( pre[ x] [ y] [ z] [ 0 ] != - 1 )
{
int xx, yy, zz;
xx= pre[ x] [ y] [ z] [ 0 ] ;
yy= pre[ x] [ y] [ z] [ 1 ] ;
zz= pre[ x] [ y] [ z] [ 2 ] ;
if ( x- xx== 1 && y- yy== 1 && s1[ x- 1 ] == s2[ y- 1 ] ) ans[ maxv-- ] = s1[ x- 1 ] ;
x= xx; y= yy; z= zz;
}
for ( int i= 1 ; i<= len; ++ i)
printf ( "%c" , ans[ i] ) ;
printf ( "\n" ) ;
}
return 0 ;
}