بالنظر إلى تسلسلين، قم بطباعة جميع التسلسلات اللاحقة الأطول الموجودة في كل منهما.
أمثلة:
Input: string X = 'AGTGATG' string Y = 'GTTAG' Output: GTAG GTTG Input: string X = 'AATCC' string Y = 'ACACG' Output: ACC AAC Input: string X = 'ABCBDAB' string Y = 'BDCABA' Output: BCAB BCBA BDAB
لقد ناقشنا مشكلة أطول تسلسل مشترك (LCS). هنا . كانت الوظيفة التي تمت مناقشتها هناك هي العثور على طول LCS. لقد ناقشنا أيضًا كيفية طباعة أطول تسلسل لاحق هنا . ولكن نظرًا لأن LCS لسلسلتين ليس فريدًا في هذا المنشور، فسنقوم بطباعة جميع الحلول الممكنة لمشكلة LCS.
فيما يلي خوارزمية مفصلة لطباعة كافة LCS.
نقوم ببناء جدول L[m+1][n+1] كما تمت مناقشته في سابق نشر واجتياز المصفوفة ثنائية الأبعاد بدءًا من L [m] [n]. للخلية الحالية L[i][j] في المصفوفة
أ) إذا كانت الأحرف الأخيرة من X وY متماثلة (أي X[i-1] == Y[j-1]) فيجب أن يكون الحرف موجودًا في جميع LCS للسلسلة الفرعية X[0...i-1] وY[0..j-1]. نحن ببساطة نكرر L[i-1] [j-1] في المصفوفة ونلحق الحرف الحالي بجميع LCS الممكنة للسلسلة الفرعية X[0...i-2] وY[0...j-2].
ب) إذا كانت الأحرف الأخيرة من X وY غير متماثلة (أي X[i-1] != Y[j-1]) فيمكن إنشاء LCS من أي من الجانب العلوي للمصفوفة (أي L[i-1][j]) أو من الجانب الأيسر من المصفوفة (أي L[i][j-1]) اعتمادًا على القيمة الأكبر. إذا كانت كلتا القيمتين متساويتين (أي L[i-1] [j] == L [i] [j-1]) فسيتم بناؤها من جانبي المصفوفة. لذا، استنادًا إلى القيم الموجودة في L[i-1] [j] وL [i] [j-1] فإننا نسير في اتجاه قيمة أكبر أو نسير في كلا الاتجاهين إذا كانت القيم متساوية.
فيما يلي التنفيذ العودي للفكرة المذكورة أعلاه -
/* Dynamic Programming implementation of LCS problem */ #include using namespace std; // Maximum string length #define N 100 int L[N][N]; /* Returns set containing all LCS for X[0..m-1] Y[0..n-1] */ set<string> findLCS(string X string Y int m int n) { // construct a set to store possible LCS set<string> s; // If we reaches end of either string return // a empty set if (m == 0 || n == 0) { s.insert(''); return s; } // If the last characters of X and Y are same if (X[m - 1] == Y[n - 1]) { // recurse for X[0..m-2] and Y[0..n-2] in // the matrix set<string> tmp = findLCS(X Y m - 1 n - 1); // append current character to all possible LCS // of substring X[0..m-2] and Y[0..n-2]. for (string str : tmp) s.insert(str + X[m - 1]); } // If the last characters of X and Y are not same else { // If LCS can be constructed from top side of // the matrix recurse for X[0..m-2] and Y[0..n-1] if (L[m - 1][n] >= L[m][n - 1]) s = findLCS(X Y m - 1 n); // If LCS can be constructed from left side of // the matrix recurse for X[0..m-1] and Y[0..n-2] if (L[m][n - 1] >= L[m - 1][n]) { set<string> tmp = findLCS(X Y m n - 1); // merge two sets if L[m-1][n] == L[m][n-1] // Note s will be empty if L[m-1][n] != L[m][n-1] s.insert(tmp.begin() tmp.end()); } } return s; } /* Returns length of LCS for X[0..m-1] Y[0..n-1] */ int LCS(string X string Y int m int n) { // Build L[m+1][n+1] in bottom up fashion for (int i = 0; i <= m; i++) { for (int j = 0; j <= n; j++) { if (i == 0 || j == 0) L[i][j] = 0; else if (X[i - 1] == Y[j - 1]) L[i][j] = L[i - 1][j - 1] + 1; else L[i][j] = max(L[i - 1][j] L[i][j - 1]); } } return L[m][n]; } /* Driver program to test above function */ int main() { string X = 'AGTGATG'; string Y = 'GTTAG'; int m = X.length(); int n = Y.length(); cout << 'LCS length is ' << LCS(X Y m n) << endl; set<string> s = findLCS(X Y m n); for (string str : s) cout << str << endl; return 0; }
Java /* Dynamic Programming implementation of LCS problem */ import java.util.*; class GFG { // Maximum String length static int N = 100; static int [][]L = new int[N][N]; /* Returns set containing all LCS for X[0..m-1] Y[0..n-1] */ static Set<String> findLCS(String X String Y int m int n) { // construct a set to store possible LCS Set<String> s = new HashSet<>(); // If we reaches end of either String // return a empty set if (m == 0 || n == 0) { s.add(''); return s; } // If the last characters of X and Y are same if (X.charAt(m - 1) == Y.charAt(n - 1)) { // recurse for X[0..m-2] and Y[0..n-2] // in the matrix Set<String> tmp = findLCS(X Y m - 1 n - 1); // append current character to all possible LCS // of subString X[0..m-2] and Y[0..n-2]. for (String str : tmp) s.add(str + X.charAt(m - 1)); } // If the last characters of X and Y are not same else { // If LCS can be constructed from top side of // the matrix recurse for X[0..m-2] and Y[0..n-1] if (L[m - 1][n] >= L[m][n - 1]) s = findLCS(X Y m - 1 n); // If LCS can be constructed from left side of // the matrix recurse for X[0..m-1] and Y[0..n-2] if (L[m][n - 1] >= L[m - 1][n]) { Set<String> tmp = findLCS(X Y m n - 1); // merge two sets if L[m-1][n] == L[m][n-1] // Note s will be empty if L[m-1][n] != L[m][n-1] s.addAll(tmp); } } return s; } /* Returns length of LCS for X[0..m-1] Y[0..n-1] */ static int LCS(String X String Y int m int n) { // Build L[m+1][n+1] in bottom up fashion for (int i = 0; i <= m; i++) { for (int j = 0; j <= n; j++) { if (i == 0 || j == 0) L[i][j] = 0; else if (X.charAt(i - 1) == Y.charAt(j - 1)) L[i][j] = L[i - 1][j - 1] + 1; else L[i][j] = Math.max(L[i - 1][j] L[i][j - 1]); } } return L[m][n]; } // Driver Code public static void main(String[] args) { String X = 'AGTGATG'; String Y = 'GTTAG'; int m = X.length(); int n = Y.length(); System.out.println('LCS length is ' + LCS(X Y m n)); Set<String> s = findLCS(X Y m n); for (String str : s) System.out.println(str); } } // This code is contributed by 29AjayKumar
Python3 # Dynamic Programming implementation of LCS problem # Maximum string length N = 100 L = [[0 for i in range(N)] for j in range(N)] # Returns set containing all LCS # for X[0..m-1] Y[0..n-1] def findLCS(x y m n): # construct a set to store possible LCS s = set() # If we reaches end of either string return # a empty set if m == 0 or n == 0: s.add('') return s # If the last characters of X and Y are same if x[m - 1] == y[n - 1]: # recurse for X[0..m-2] and Y[0..n-2] in # the matrix tmp = findLCS(x y m - 1 n - 1) # append current character to all possible LCS # of substring X[0..m-2] and Y[0..n-2]. for string in tmp: s.add(string + x[m - 1]) # If the last characters of X and Y are not same else: # If LCS can be constructed from top side of # the matrix recurse for X[0..m-2] and Y[0..n-1] if L[m - 1][n] >= L[m][n - 1]: s = findLCS(x y m - 1 n) # If LCS can be constructed from left side of # the matrix recurse for X[0..m-1] and Y[0..n-2] if L[m][n - 1] >= L[m - 1][n]: tmp = findLCS(x y m n - 1) # merge two sets if L[m-1][n] == L[m][n-1] # Note s will be empty if L[m-1][n] != L[m][n-1] for i in tmp: s.add(i) return s # Returns length of LCS for X[0..m-1] Y[0..n-1] def LCS(x y m n): # Build L[m+1][n+1] in bottom up fashion for i in range(m + 1): for j in range(n + 1): if i == 0 or j == 0: L[i][j] = 0 else if x[i - 1] == y[j - 1]: L[i][j] = L[i - 1][j - 1] + 1 else: L[i][j] = max(L[i - 1][j] L[i][j - 1]) return L[m][n] # Driver Code if __name__ == '__main__': x = 'AGTGATG' y = 'GTTAG' m = len(x) n = len(y) print('LCS length is' LCS(x y m n)) s = findLCS(x y m n) for i in s: print(i) # This code is contributed by # sanjeev2552
C# // Dynamic Programming implementation // of LCS problem using System; using System.Collections.Generic; class GFG { // Maximum String length static int N = 100; static int []L = new int[N N]; /* Returns set containing all LCS for X[0..m-1] Y[0..n-1] */ static HashSet<String> findLCS(String X String Y int m int n) { // construct a set to store possible LCS HashSet<String> s = new HashSet<String>(); // If we reaches end of either String // return a empty set if (m == 0 || n == 0) { s.Add(''); return s; } // If the last characters of X and Y are same if (X[m - 1] == Y[n - 1]) { // recurse for X[0..m-2] and Y[0..n-2] // in the matrix HashSet<String> tmp = findLCS(X Y m - 1 n - 1); // append current character to all possible LCS // of subString X[0..m-2] and Y[0..n-2]. foreach (String str in tmp) s.Add(str + X[m - 1]); } // If the last characters of X and Y are not same else { // If LCS can be constructed from top side of // the matrix recurse for X[0..m-2] and Y[0..n-1] if (L[m - 1 n] >= L[m n - 1]) s = findLCS(X Y m - 1 n); // If LCS can be constructed from left side of // the matrix recurse for X[0..m-1] and Y[0..n-2] if (L[m n - 1] >= L[m - 1 n]) { HashSet<String> tmp = findLCS(X Y m n - 1); // merge two sets if L[m-1n] == L[mn-1] // Note s will be empty if L[m-1n] != L[mn-1] foreach (String str in tmp) s.Add(str); } } return s; } /* Returns length of LCS for X[0..m-1] Y[0..n-1] */ static int LCS(String X String Y int m int n) { // Build L[m+1n+1] in bottom up fashion for (int i = 0; i <= m; i++) { for (int j = 0; j <= n; j++) { if (i == 0 || j == 0) L[i j] = 0; else if (X[i - 1] == Y[j - 1]) L[i j] = L[i - 1 j - 1] + 1; else L[i j] = Math.Max(L[i - 1 j] L[i j - 1]); } } return L[m n]; } // Driver Code public static void Main(String[] args) { String X = 'AGTGATG'; String Y = 'GTTAG'; int m = X.Length; int n = Y.Length; Console.WriteLine('LCS length is ' + LCS(X Y m n)); HashSet<String> s = findLCS(X Y m n); foreach (String str in s) Console.WriteLine(str); } } // This code is contributed by Rajput-Ji
JavaScript <script> /* Dynamic Programming implementation of LCS problem */ // Maximum String length let N = 100; let L = new Array(N); for(let i=0;i<N;i++) { L[i]=new Array(N); } /* Returns set containing all LCS for X[0..m-1] Y[0..n-1] */ function findLCS(XYmn) { // construct a set to store possible LCS let s = new Set(); // If we reaches end of either String // return a empty set if (m == 0 || n == 0) { s.add(''); return s; } // If the last characters of X and Y are same if (X[m-1] == Y[n-1]) { // recurse for X[0..m-2] and Y[0..n-2] // in the matrix let tmp = findLCS(X Y m - 1 n - 1); // append current character to all possible LCS // of subString X[0..m-2] and Y[0..n-2]. for (let str of tmp.values()) s.add(str + X[m-1]); } // If the last characters of X and Y are not same else { // If LCS can be constructed from top side of // the matrix recurse for X[0..m-2] and Y[0..n-1] if (L[m - 1][n] >= L[m][n - 1]) s = findLCS(X Y m - 1 n); // If LCS can be constructed from left side of // the matrix recurse for X[0..m-1] and Y[0..n-2] if (L[m][n - 1] >= L[m - 1][n]) { let tmp = findLCS(X Y m n - 1); // merge two sets if L[m-1][n] == L[m][n-1] // Note s will be empty if L[m-1][n] != L[m][n-1] for (let item of tmp.values()) s.add(item) } } return s; } /* Returns length of LCS for X[0..m-1] Y[0..n-1] */ function LCS(XYmn) { // Build L[m+1][n+1] in bottom up fashion for (let i = 0; i <= m; i++) { for (let j = 0; j <= n; j++) { if (i == 0 || j == 0) L[i][j] = 0; else if (X[i-1] == Y[j-1]) L[i][j] = L[i - 1][j - 1] + 1; else L[i][j] = Math.max(L[i - 1][j] L[i][j - 1]); } } return L[m][n]; } // Driver Code let X = 'AGTGATG'; let Y = 'GTTAG'; let m = X.length; let n = Y.length; document.write('LCS length is ' + LCS(X Y m n)+'
'); let s = findLCS(X Y m n); for (let str of s.values()) document.write(str+'
'); // This code is contributed by rag2127 </script>
الإخراج:
LCS length is 4 GTAG GTTG
تعقيد الوقت: سيكون الأمر أسيًا لأننا نستخدم العودية للعثور على جميع LCS الممكنة.
تعقيد الفضاء: يا (ن * ن)
مراجع: Wikibooks - قراءة جميع LCSs