最长公共子序列

模板题链接:P2516 HAOI2010最长公共子序列

我们借题解第一篇的巨佬的图

我们O(n2)的枚举i,j(分别对应两个串的下标)

我们记两串分别为a,b,记dp[i][j]为截止到i,j时的最长公共子序列,如果a[i]==b[j]匹配成功,我们可直接用dp[i1][j1]+1来扩展dp[i][j],相当于在网格图中连一条斜边。若没有斜边,我们就通过dp[i1][j]dp[i][j1]max来扩展。

对于方案的统计,和上面是同理的,只需注意在dp[i1][j1]=dp[i][j]时,dp[i][j1]dp[i1][j1]dp[i1][j1]转移来,再分别转移到dp[i][j],是同一种情况,但是被计数了两次,所以要减掉一份。

1

代码如下:(加了滚动数组)

#include<bits/stdc++.h>
using namespace std;
#define file(a) freopen(#a".in","r",stdin),freopen(#a".out","w",stdout)
#define LL long long
#define N 5010
#define mods (LL)(1e8)
char a[N],b[N];
LL dp[2][N];
LL cnt[2][N];
inline LL Max(LL x,LL y){
	return x>y?x:y;
}
void LCS()
{
	bool now=1,last=0;
	int lena=strlen(a+1),lenb=strlen(b+1);
	//printf("%d %d\n",lena,lenb);
	for(int i=0;i<=lenb;++i) cnt[0][i]=1;
	cnt[1][0]=1;
	for(int i=1;i<=lena;++i,now^=1,last^=1)
	{
		for(int j=1;j<=lenb;++j)
		{
			cnt[now][j]=0;
			dp[now][j]=((a[i]==b[j])?dp[last][j-1]+1:Max(dp[last][j],dp[now][j-1]));
			if(a[i]==b[j]){
				cnt[now][j]+=cnt[last][j-1];
			}
			if(dp[now][j]==dp[now][j-1]){
				cnt[now][j]+=cnt[now][j-1];
			}
			if(dp[now][j]==dp[last][j]){
				cnt[now][j]+=cnt[last][j];
			}
			if(dp[now][j]==dp[last][j-1]){
				cnt[now][j]-=cnt[last][j-1];
			}
			cnt[now][j]%=mods;
		}
	}
	printf("%lld\n%lld",dp[last][lenb],cnt[last][lenb]);
}
int main(){
	int top=0;
	char ch=getchar();
	while(ch!='.') {a[++top]=ch;ch=getchar();}
	//cout<<top<<endl;
	ch=getchar();
	top=0;ch=getchar();
	while(ch!='.') {b[++top]=ch;ch=getchar();}
	//cout<<top<<endl;
	LCS();
	return 0;
}

posted @   cbdsopa  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示