📜  在给定的 K 个排列中找到最长公共子序列 (LCS)

📅  最后修改于: 2022-05-13 01:56:08.085000             🧑  作者: Mango

在给定的 K 个排列中找到最长公共子序列 (LCS)

给定二维数组arr[][]中从1 到 NK个数字排列。任务是找到这些 K 个排列的最长公共子序列。

例子:

方法:这个问题是最长公共子序列的扩展。该解决方案基于动态规划的概念。请按照以下步骤操作:

  • 创建一个二维数组(pos[][]) 来存储每个序列中从 1 到 N 的所有数字的位置,其中 pos[i][j] 表示值 j 在第 i 个序列中的位置。
  • 初始化一个数组(dp[]),其中dp[i]存储在位置 i 结束的最长公共子序列。
    • 第一个序列视为参考,并为第一个序列的每个元素检查它们在其他序列中的相对位置
      • 遍历所有可能的索引 j 使得j < i并查看第一个序列索引 i处的值是否可以附加以 j 结尾的最长递增子序列。
      • 这是通过检查数字arr[0][j]位置是否小于等于值 arr[0][i]在所有排列中的位置来完成的。然后 arr[0][i] 处的值可以附加到以位置 j 结尾的序列。
  • 所以递归是dp[i] = max(dp[i], 1 + dp[j])
  • 数组 dp[] 的最大值就是答案。

请参见下图:

下面是上述方法的实现。

C++
// C++ code to find the longest common
// sub sequence of k permutations.
#include 
using namespace std;
 
// Function to find the longest common
// sub sequence of k permutations.
int findLcs(vector> &arr,
            int n, int k)
{
    // Variable to keep track of the length
    // of the longest common sub sequence
    int maxLen = 0;
 
    // position array to keep track
    // of position of elements
    // in each permutation
    int pos[k][n];
 
    // Array to store the length of LCS
    int dp[n];
 
    for (int i = 0; i < k; i++)
    {
        for (int j = 0; j < n; j++)
        {
            pos[i][arr[i][j] - 1] = j;
        }
    }
     
    // Loop to calculate the LCS
    // of all the permutations
    for (int i = 0; i < n; i++)
    {
        dp[i] = 1;
        for (int j = 0; j < i; j++)
        {
            bool good = true;
            for (int p = 0; p < k; p++)
            {
                if (pos[p][arr[0][j] - 1]
                    > pos[p][arr[0][i] - 1])
                {
                    good = false;
                    break;
                }
            }
            if (good)
            {
                dp[i] = max(dp[i], 1 + dp[j]);
                maxLen = max(maxLen, dp[i]);
            }
        }
    }
    return maxLen;
}
 
// Driver code
int main()
{
    vector> arr =
    {{2, 5, 1, 4, 6, 3},
     {5, 1, 4, 3, 2, 6},
     {5, 4, 2, 6, 3, 1}};
    int N = arr[0].size();
    int K = 3;
 
    // Function Call
    cout << findLcs(arr, N, K);
 
    return 0;
}


Java
// Java code to find the longest common
// sub sequence of k permutations.
import java.util.*;
 
class GFG{
 
// Function to find the longest common
// sub sequence of k permutations.
static int findLcs(int[][]arr,
            int n, int k)
{
    // Variable to keep track of the length
    // of the longest common sub sequence
    int maxLen = 0;
 
    // position array to keep track
    // of position of elements
    // in each permutation
    int [][]pos = new int[k][n];
 
    // Array to store the length of LCS
    int []dp = new int[n];
 
    for (int i = 0; i < k; i++)
    {
        for (int j = 0; j < n; j++)
        {
            pos[i][arr[i][j] - 1] = j;
        }
    }
     
    // Loop to calculate the LCS
    // of all the permutations
    for (int i = 0; i < n; i++)
    {
        dp[i] = 1;
        for (int j = 0; j < i; j++)
        {
            boolean good = true;
            for (int p = 0; p < k; p++)
            {
                if (pos[p][arr[0][j] - 1]
                    > pos[p][arr[0][i] - 1])
                {
                    good = false;
                    break;
                }
            }
            if (good)
            {
                dp[i] = Math.max(dp[i], 1 + dp[j]);
                maxLen = Math.max(maxLen, dp[i]);
            }
        }
    }
    return maxLen;
}
 
// Driver code
public static void main(String[] args)
{
    int[][] arr =
    {{2, 5, 1, 4, 6, 3},
     {5, 1, 4, 3, 2, 6},
     {5, 4, 2, 6, 3, 1}};
    int N = arr[0].length;
    int K = 3;
 
    // Function Call
    System.out.print(findLcs(arr, N, K));
}
}
 
// This code is contributed by shikhasingrajput


Python3
# Python code for the above approach
 
# Function to find the longest common
# sub sequence of k permutations.
def findLcs(arr, n, k):
 
    # Variable to keep track of the length
    # of the longest common sub sequence
    maxLen = 0
 
    # position array to keep track
    # of position of elements
    # in each permutation
    pos = [0] * k
    for i in range(len(pos)):
        pos[i] = [0] * n
 
    # Array to store the length of LCS
    dp = [0] * n
 
    for i in range(k):
        for j in range(n):
            pos[i][arr[i][j] - 1] = j
 
    # Loop to calculate the LCS
    # of all the permutations
    for i in range(n):
        dp[i] = 1
        for j in range(i):
            good = True
            for p in range(k):
                if (pos[p][arr[0][j] - 1] > pos[p][arr[0][i] - 1]):
                    good = False
                    break
            if (good):
                dp[i] = max(dp[i], 1 + dp[j])
                maxLen = max(maxLen, dp[i])
    return maxLen
 
# Driver code
arr = [[2, 5, 1, 4, 6, 3], [5, 1, 4, 3, 2, 6], [5, 4, 2, 6, 3, 1]]
N = len(arr[0])
K = 3
 
# Function Call
print(findLcs(arr, N, K))
 
# This code is contributed by Saurabh Jaiswal


C#
// C# code to find the longest common
// sub sequence of k permutations.
using System;
 
class GFG {
 
    // Function to find the longest common
    // sub sequence of k permutations.
    static int findLcs(int[, ] arr, int n, int k)
    {
        // Variable to keep track of the length
        // of the longest common sub sequence
        int maxLen = 0;
 
        // position array to keep track
        // of position of elements
        // in each permutation
        int[, ] pos = new int[k, n];
 
        // Array to store the length of LCS
        int[] dp = new int[n];
 
        for (int i = 0; i < k; i++) {
            for (int j = 0; j < n; j++) {
                pos[i, arr[i, j] - 1] = j;
            }
        }
 
        // Loop to calculate the LCS
        // of all the permutations
        for (int i = 0; i < n; i++) {
            dp[i] = 1;
            for (int j = 0; j < i; j++) {
                bool good = true;
                for (int p = 0; p < k; p++) {
                    if (pos[p, arr[0, j] - 1]
                        > pos[p, arr[0, i] - 1]) {
                        good = false;
                        break;
                    }
                }
                if (good) {
                    dp[i] = Math.Max(dp[i], 1 + dp[j]);
                    maxLen = Math.Max(maxLen, dp[i]);
                }
            }
        }
        return maxLen;
    }
 
    // Driver code
    public static void Main(string[] args)
    {
        int[, ] arr = { { 2, 5, 1, 4, 6, 3 },
                        { 5, 1, 4, 3, 2, 6 },
                        { 5, 4, 2, 6, 3, 1 } };
        int N = arr.GetLength(1);
        int K = 3;
 
        // Function Call
        Console.WriteLine(findLcs(arr, N, K));
    }
}
 
// This code is contributed by ukasp.


Javascript



输出
3

时间复杂度: O(N 2 * K)
辅助空间: O(N * K)