Gym-100989B并查集

B. LCS (B)
time limit per test
0.25 s
memory limit per test
256 MB
input
standard input
output
standard output

Although Haneen was able to solve the LCS problem, Dr. Ibrahim is suspicious about whether she really understands the LCS problem or not. He believes that she can't write the code on her own, but can only translate the LCS pseudo-code given in class into C++ code without really understanding how it works. Here is the pseudo-code Dr. Ibrahim gave in class:

function LCS (A[1..R], B[1..C])
DP = array(0..R, 0..C)
for i := 0..R
DP[i,0] = 0
for j := 0..C
DP[0,j] = 0
for i := 1..R
for j := 1..C
if A[i] = B[j]
DP[i,j] := DP[i-1,j-1] + 1
else
DP[i,j] := max(DP[i,j-1], DP[i-1,j])
return DP[R,C]

To verify that Haneen understands the LCS problem, Dr. Ibrahim asked her to solve the following problem:

After running the above LCS code on two strings A and B, the 2D array DP is filled with values. Given the 2D array DP, can you guess what A and B are? Any two strings A and B that will produce the given table and contain only lowercase English letters are acceptable.

Can you help Haneen solve this problem?

Input

The first line of input contains two integers R and C (1 ≤ R, C ≤ 25), the length of the strings A and B, respectively.

Each of the following R + 1 lines contains C + 1 integers, these lines represent the 2D array DP.

It's guaranteed that the given table was produced by running the algorithm on two strings that contain only lowercase English letters.

Output

Print string A on the first line and string B on the second line. Both strings should contain only lowercase English letters.

Example
input
Copy
3 4
0 0 0 0 0
0 0 1 1 1
0 0 1 1 2
0 1 1 1 2
output
Copy
abc
cadb

题目的大概意思就是,用输出的两个字符串,进行dp运算,算法就是题目上那个,得出来的结果就是输入的结果,现在就是要用输入的数字推算出字符串来.....这道题可以用并查集。(其实就是看了大佬的代码才会的......)

首先第一条字符串我们就可以设成abcdefg.....因为数字是由第二条字符串得来的,所以我们只需要推算第二条字符串就可以

题目中的dp运算
if A[i] = B[j]
DP[i,j] := DP[i-1,j-1] + 1
else
DP[i,j] := max(DP[i,j-1], DP[i-1,j])

所以我们可以反过来推算

if (i>0&&j>0&&dp[i][j]>max(dp[i-1][j],dp[i][j-1]))    //如果dp[i][j]都大于,那么可以判断a[i-1]==b[j-1]
	pre[find(j-1+n)]=find(i-1);                   //pre表示自己的父节点,这里是让b[j-1]的父节点为a[i-1]

然后就可以算出b的字符串了

AC代码:

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=30;
int dp[maxn][maxn];
char num1[maxn],num2[maxn];
int pre[maxn*2];
int find(int x)
{
	if (x!=pre[x])
		return vis[x]=find(pre[x]);
	return pre[x];
}
int main()
{
	int n,m,i,j,k;
	cin>>n>>m;
	for (i=0;i<n+m;i++)
		pre[i]=i;
	for (i=0;i<=n;i++)
		for (j=0;j<=m;j++)
			{
				cin>>dp[i][j];
				if (i>0&&j>0&&dp[i][j]>max(dp[i-1][j],dp[i][j-1]))
					pre[find(j-1+n)]=find(i-1);
			}
	for (i=0;i<n;i++)
		num1[i]='a'+find(i);
	for (i=n;i<n+m;i++)
		if (pre[i]==i)
			num2[i-n]='z';                //因为数据是1<=n<=25,所以'z'不会对数据有影响
		else num2[i-n]='a'+find(i);          // if pre[i]!=i  说明有了父节点
	cout<<num1<<endl<<num2<<endl;
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值