可以考虑分别从A串和B串中都取出一段序列,取出的这段序列满足存在子序列C
然后对剩余的序列分别求最长公共子序列。
Ps:
卡常大法好!第一次卡到
rank1
~ 但是代码又长又丑
#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;
return 0;
}