Gym - 100989B

 

题目描述:

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

3 4
0 0 0 0 0
0 0 1 1 1
0 0 1 1 2
0 1 1 1 2

Output

abc
cadb

大意:给你一个由两个序列求lcs打出的dp表  求出这两个序列

分暴力和并查集两种做法(暴力的勉强理解,并查集还看不懂,有待后续更新)

暴力法:

当我们得到(dp[a1][b1]==dp[a1-1][b1-1]+1&&dp[a1][b1]!=max(dp[a1-1][b1],dp[a1][b1-1]))这个式子时

我们可以得出a[a1]==b[b1]

 

 

 

因为字符串长度<=25,然后可以先假设A字符串就是abcdef....,然后根据A算B就行。b[j]未确定时,令b[j]=a[i]即可;遇到b[j]已确定的情况就改变a[i],以及所有跟a[i]相同的字符。(包括a数组和b数组中所有等于a[i]的字符,因为这个a[i]可能本身是一个未确定的值,所以由这个未确定的a[i]得到的此前的b[j]和此前的a[i]都要改变)

 

最后遇到没有被访问过的b[j]时,只需要将b[j]赋值为再a中没有出现过的字母即可(或者直接赋值为z,因为字符长度小于等于25)

 

代码:

#include<iostream>

#include<cstring>
#include<cstdio>
#include<map>
#include<set>
#include<string>
#include<algorithm>
using namespace std;

int main()

{

    int a,b;
    cin>>a>>b;
    int dp[30][30],visb[30];
    char al[30],bl[30];
    Me0(dp);
    Me0(visb);
    for(int a1=0;a1<=a;a1++)
    {
        for(int b1=0;b1<=b;b1++)
        {
            cin>>dp[a1][b1];
        }
    }
    for(int a1=0;a1<a;a1++)
    {
        al[a1]='a'+a1;
    }
    al[a]=bl[b]='\0';
    for(int a1=1;a1<=a;a1++)
    {
        for(int b1=1;b1<=b;b1++)
        {
            if(dp[a1][b1]==dp[a1-1][b1-1]+1&&dp[a1][b1]!=max(dp[a1-1][b1],dp[a1][b1-1]))
            {
                if(visb[b1-1]==0)
                {
                    bl[b1-1]=al[a1-1];
                    visb[b1-1]=1;
                }
                else
                {
                    for(int k=0;k<b;k++)
                    {
                        if(bl[k]==al[a1-1])
                        {
                            bl[k]=bl[b1-1];
                        }
                    }
                    for(int k=0;k<a;k++)
                    {
                        if(al[k]==al[a1-1]&&k!=a1-1)
                        {
                            al[k]=bl[b1-1];
                        }
                    }
                    al[a1-1]=bl[b1-1];
                }
            }
        }
    }
    int flag[26];
    Me0(flag);
    for(int a1=0;a1<a;a1++)
    {
        flag[al[a1]-'a']=1;
    }
    int temp;
    for(int a1=0;a1<26;a1++)
    {
        if(flag[a1]==0)
        {
            temp=a1;
            break;
        }
    }
    for(int b1=0;b1<b;b1++)
    {
        if(visb[b1]==0)
        {
            bl[b1]=temp+'a';
        }
    }
    printf("%s\n%s\n",al,bl);
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值