TRIP-LCS方案输出

首先肯定是要求lcs的,这个我懒得讲了。。。

因为lcs最多就是这个串的长度,所以我们可以考虑dfs。我们开2个数组,f1[i][j]表示在a串中,f2[i][j]表示在b串中,j之前的第一个‘a’+j在什么地方。

因为我们递归的时候知道了lcs的长度,所以我们可以用枚举每一位是啥的方式递归。(26^80emmmm但是可以剪枝)

因为知道了每一位是啥,所以我们就可以轻易求出上一个的位置。如果这个位置不存在,那就不太行。递归返回。

如果存在就比较ok,就继续递归。。。

#include <bits/stdc++.h>

using namespace std;
const int maxn=1005;
int T;int tot=0;
string s1,s2;
int f[maxn][maxn],f1[maxn][maxn],f2[maxn][maxn];
string ans[maxn];
void print(int i,int j)
{
	if(i==0||j==0) return;
	if(f[i][j]==f[i-1][j-1]+1)
	{
		print(i-1,j-1);
		
	}
}
void find(int n1,int n2,string s,int l)
{
	if(n1<0||n2<0) return ;
	if(l<=0) {ans[++tot]=s;return;}
	for(int i=1;i<=26;i++)
	{
		int p1=f1[i][n1],p2=f2[i][n2];
		if(f[p1][p2]!=l) continue;
		char ch=i+96;
		find(p1-1,p2-1,ch+s,l-1);
	}
}
void work()
{
	tot=0;
	cin>>s1>>s2;
	int n1=s1.size(),n2=s2.size();
	s1='.'+s1;s2='.'+s2;
	memset(f,0,sizeof(f));memset(f1,0,sizeof(f1));memset(f2,0,sizeof(f2));
	for(int i=1;i<=26;i++)
	{
		for(int j=1;j<=n1;j++)
		{
			if(s1[j]==i+96) f1[i][j]=j;
			else f1[i][j]=f1[i][j-1];
		}
		for(int j=1;j<=n2;j++)
		{
			if(s2[j]==i+96) f2[i][j]=j;
			else f2[i][j]=f2[i][j-1];
		}
	}
	for(int i=1;i<=n1;i++)
	{
		for(int j=1;j<=n2;j++)
		{
			f[i][j]=max(f[i-1][j],f[i][j-1]);
			if(s1[i]==s2[j])
			{
				f[i][j]=max(f[i][j],f[i-1][j-1]+1);
			}
		}
	}
	find(n1,n2,"",f[n1][n2]);
//	cout<<f[n1][n2]<<endl;
//	print(n1,n2);
	sort(ans+1,ans+1+tot);
	for(int i=1;i<=tot;i++) cout<<ans[i]<<endl;
}
int main()
{
	scanf("%d",&T);
	for(int ti=1;ti<=T;ti++)
	{
		work();
	}
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
最长公共子序列(LCS)是两个序列中都存在的最长子序列。为了修改算法 LCS 使其输出最长公共子序列,我们需要在 LCS 算法的基础上进行一些修改,具体步骤如下: 1. 构造一个二维数组 dp,其中 dp[i][j] 表示序列 A 中前 i 个元素和序列 B 中前 j 个元素的最长公共子序列长度。 2. 初始化 dp 数组的第一行和第一列,即 dp[0][j] 和 dp[i][0] 均为 0。 3. 对于序列 A 和序列 B 中的每一个元素,判断它们是否相等。 4. 如果 A[i] 和 B[j] 相等,则 dp[i][j] = dp[i-1][j-1] + 1。 5. 如果 A[i] 和 B[j] 不相等,则 dp[i][j] = max(dp[i-1][j], dp[i][j-1])。 6. 最终,最长公共子序列的长度为 dp[m][n],其中 m 和 n 分别为序列 A 和序列 B 的长度。 7. 根据 dp 数组求出最长公共子序列。从 dp[m][n] 开始,如果 A[i] 和 B[j] 相等,则将该元素加入最长公共子序列中,然后向左上方移动一格,即 i--,j--;如果不相等,则向较大的方向移动一格。 代码如下: ```python def LCS(A, B): m, n = len(A), len(B) dp = [[0] * (n+1) for _ in range(m+1)] # 构造二维数组 for i in range(1, m+1): for j in range(1, n+1): if A[i-1] == B[j-1]: dp[i][j] = dp[i-1][j-1] + 1 else: dp[i][j] = max(dp[i-1][j], dp[i][j-1]) # 求最长公共子序列 lcs = '' i, j = m, n while i > 0 and j > 0: if A[i-1] == B[j-1]: lcs = A[i-1] + lcs i -= 1 j -= 1 elif dp[i-1][j] > dp[i][j-1]: i -= 1 else: j -= 1 return lcs ``` 该算法的时间复杂度为 $O(mn)$,其中 m 和 n 分别为序列 A 和序列 B 的长度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值