C++ 中的最短公共超序列
假设我们有两个字符串 str1 和 str2,我们需要找到一个最短的字符串,它同时包含 str1 和 str2 作为子序列。可能存在多个结果,因此我们只需要返回其中一个。
如你所知,如果从字符串 T 中删除一些字符(可能为 0 个,并且这些字符可以从 T 中的任意位置选择)得到字符串 S,则称字符串 S 为字符串 T 的子序列。
因此,如果输入为 "acab" 和 "bac",则输出将为 "bacab",这是因为这两个给定的字符串都是其子序列。
为了解决这个问题,我们将遵循以下步骤:
定义一个函数 getLCS(),它将接收 s1 和 s2 作为输入,
ret := 空字符串
n := s1 的大小,m := s2 的大小
定义一个大小为 (n + 1) x (m + 1) 的二维数组 dp
i := n,j := m
s1 := 在 s1 前面连接空字符串
s2 := 在 s2 前面连接空字符串
对于初始化 i := 1,当 i <= n 时,更新(i 增加 1),执行以下操作:
对于初始化 j := 1,当 j <= m 时,更新(j 增加 1),执行以下操作:
如果 s1[i] 与 s2[j] 相同,则:
dp[i, j] := 1 + dp[i - 1, j - 1]
否则
dp[i, j] := dp[i - 1, j] 和 dp[i, j - 1] 的最大值
当 (i 非零且 j 非零) 时,执行以下操作:
如果 dp[i, j] 与 dp[i - 1, j] 相同,则:
(i 减 1)
忽略以下部分,跳到下一个迭代
如果 dp[i, j] 与 dp[i, j - 1] 相同,则:
(j 减 1)
忽略以下部分,跳到下一个迭代
ret := ret + s1[i]
(i 减 1)
(j 减 1)
反转数组 ret
返回 ret
从主方法执行以下操作:
s3 := getLCS(str1, str2)
ret := 空字符串,i := 0,j := 0,k := 0
当 k < s3 的大小 时,执行以下操作:
如果 i < str1 的大小 且 str1[i] 不等于 s3[k],则:
ret := ret + str1[i]
(i 增加 1)
忽略以下部分,跳到下一个迭代
如果 j < str2 的大小 且 str2[j] 不等于 s3[k],则:
ret := ret + str2[j]
(j 增加 1)
忽略以下部分,跳到下一个迭代
ret := ret + s3[k]
(i、j、k 增加 1)
当 i < str1 的大小 时,执行以下操作:
ret := ret + str1[i]
(i 增加 1)
当 j < str2 的大小 时,执行以下操作:
ret := ret + str2[j]
(j 增加 1)
返回 ret
让我们看看下面的实现来更好地理解:
示例
#include <bits/stdc++.h> using namespace std; class Solution { public: string shortestCommonSupersequence(string str1, string str2){ string s3 = getLCS(str1, str2); string ret = ""; int i = 0; int j = 0; int k = 0; while (k < s3.size()) { if (i < str1.size() && str1[i] != s3[k]) { ret += str1[i]; i++; continue; } if (j < str2.size() && str2[j] != s3[k]) { ret += str2[j]; j++; continue; } ret += s3[k]; k++; i++; j++; } while (i < str1.size()) { ret += str1[i]; i++; } while (j < str2.size()) { ret += str2[j]; j++; } return ret; } string getLCS(string s1, string s2){ string ret = ""; int n = s1.size(); int m = s2.size(); vector<vector<int> > dp(n + 1, vector<int>(m + 1)); int i = n; int j = m; s1 = " " + s1; s2 = " " + s2; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { if (s1[i] == s2[j]) { dp[i][j] = 1 + dp[i - 1][j - 1]; } else { dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); } } } while (i && j) { if (dp[i][j] == dp[i - 1][j]) { i--; continue; } if (dp[i][j] == dp[i][j - 1]) { j--; continue; } ret += s1[i]; i--; j--; } reverse(ret.begin(), ret.end()); return ret; } }; main(){ Solution ob; cout << (ob.shortestCommonSupersequence("acab", "bac")); }
输入
"acab", "bac"
输出
bacab