บทนำ
โจทย์: หา Longest Common Subsequence (LCS) ทุกแบบที่เป็นไปได้ของสตริงสองตัว แล้วพิมพ์เรียง Lexicographical Order
ตัวอย่าง
str1 = "xysxysx", str2 = "xsyxsyx" LCS ทั้งหมด: xsxsx, xsxyx, xsysx, xysyx, xyxsx, xyxyx
แนวทางแก้ปัญหา
- DP หาความยาว LCS (DP[i][j] = LCS length ของ suffix i, j)
- Backtracking แบบ Lexicographical: ลองตัวอักษร 'a' ถึง 'z'
- หาตำแหน่ง i ใน str1 และ j ใน str2 ที่มีตัวอักษรนั้น และ DP[i][j] == remaining length
- Recursive สร้างสตริงต่อ
ตัวอย่างโค้ด
#include <iostream>
#include <cstring>
#define MAX 100
using namespace std;
int LCSLength = 0;
int DP[MAX][MAX];
int calcLCSLenght(string str1, string str2, int l1, int l2, int i, int j) {
int &lcsLen = DP[i][j];
if (i == l1 || j == l2) return lcsLen = 0;
if (lcsLen != -1) return lcsLen;
lcsLen = 0;
if (str1[i] == str2[j])
lcsLen = 1 + calcLCSLenght(str1, str2, l1, l2, i + 1, j + 1);
else
lcsLen = max(calcLCSLenght(str1, str2, l1, l2, i + 1, j), calcLCSLenght(str1, str2, l1, l2, i, j + 1));
return lcsLen;
}
void printAllLCS(string str1, string str2, int l1, int l2, char data[], int index1, int index2, int currentLCSlength) {
if (currentLCSlength == LCSLength) {
data[currentLCSlength] = '\0';
puts(data);
return;
}
if (index1 == l1 || index2 == l2) return;
for (char ch = 'a'; ch <= 'z'; ch++) {
bool done = false;
for (int i = index1; i < l1; i++) {
if (ch == str1[i]) {
for (int j = index2; j < l2; j++) {
if (ch == str2[j] && calcLCSLenght(str1, str2, l1, l2, i, j) == LCSLength - currentLCSlength) {
data[currentLCSlength] = ch;
printAllLCS(str1, str2, l1, l2, data, i + 1, j + 1, currentLCSlength + 1);
done = true;
break;
}
}
}
if (done) break;
}
if (done) break;
}
}
int main() {
string str1 = "xysxysx", str2 = "xsyxsyx";
int l1 = str1.length(), l2 = str2.length();
memset(DP, -1, sizeof(DP));
LCSLength = calcLCSLenght(str1, str2, l1, l2, 0, 0);
char data[MAX];
cout << "All longest common sub-sequences in lexicographical order are\n";
printAllLCS(str1, str2, l1, l2, data, 0, 0, 0);
return 0;
}
ผลลัพธ์
All longest common sub-sequences in lexicographical order are xsxsx xsxyx xsysx xysyx xyxsx xyxyx
สรุป
DP + Lexicographical Backtracking พิมพ์ LCS ทั้งหมดเรียงสวย ไม่ซ้ำ ใช้ได้กับสตริงความยาวปานกลาง