दीर्घवर्तिक सामान्य उपानुक्रम (लांगेस्ट कॉमन सब सीक्वेंस): Difference between revisions
(→जटिलता) |
|||
| Line 1: | Line 1: | ||
{{Short description|Algorithmic problem on pairs of sequences}} | {{Short description|Algorithmic problem on pairs of sequences}} | ||
{{Distinguish|सबसे लंबी सामान्य उपस्ट्रिंग}} | {{Distinguish|सबसे लंबी सामान्य उपस्ट्रिंग}} | ||
[[File:Nubio Diff Screenshot3.png|thumb|एक उदाहरण फ़ाइल के दो संशोधनों की तुलना, उनके सबसे लंबे सामान्य अनुवर्ती (काले) के आधार पर]]'''सबसे लंबा सामान्य अनुवर्ती ( | [[File:Nubio Diff Screenshot3.png|thumb|एक उदाहरण फ़ाइल के दो संशोधनों की तुलना, उनके सबसे लंबे सामान्य अनुवर्ती (काले) के आधार पर]]'''सबसे लंबा सामान्य अनुवर्ती (LCS)''' अनुक्रमों के एक सेट (अक्सर केवल दो अनुक्रम) में सभी अनुक्रमों के लिए सामान्य सबसे लंबा अनुवर्ती है। यह सबसे लंबे सामान्य सबस्ट्रिंग से भिन्न है: सबस्ट्रिंग के विपरीत, बाद के अनुक्रमों को मूल अनुक्रमों के भीतर लगातार पदों पर रहने की आवश्यकता नहीं होती है। सबसे लंबे समय तक सामान्य अनुक्रमों की गणना करने की समस्या एक क्लासिक कंप्यूटर विज्ञान समस्या है, जो अंतर उपयोगिता जैसे डेटा तुलना कार्यक्रमों का आधार है, <code>diff</code>और कम्प्यूटेशनल भाषाविज्ञान और जैव सूचना विज्ञान में इसका अनुप्रयोग है। फ़ाइलों के संशोधन-नियंत्रित संग्रह में किए गए कई परिवर्तनों को समेटने के लिए Git जैसी संशोधन नियंत्रण प्रणालियों द्वारा भी इसका व्यापक रूप से उपयोग किया जाता है। | ||
<!-- todo: add definition and example --> | <!-- todo: add definition and example --> | ||
उदाहरण के लिए, अनुक्रमों (ABCD) और (ACBAD) पर विचार करें। उनकी 5 लंबाई-2 सामान्य अनुवर्ती हैं: (AB), (AC), (AD), (BD), और (CD); 2 लंबाई-3 सामान्य अनुवर्ती: (ABD) और (ACD); और अब कोई सामान्य अनुवर्ती नहीं है। अतः (ABD) और (ACD) उनके सबसे लंबे सामान्य अनुवर्ती हैं। | उदाहरण के लिए, अनुक्रमों (ABCD) और (ACBAD) पर विचार करें। उनकी 5 लंबाई-2 सामान्य अनुवर्ती हैं: (AB), (AC), (AD), (BD), और (CD); 2 लंबाई-3 सामान्य अनुवर्ती: (ABD) और (ACD); और अब कोई सामान्य अनुवर्ती नहीं है। अतः (ABD) और (ACD) उनके सबसे लंबे सामान्य अनुवर्ती हैं। | ||
| Line 15: | Line 15: | ||
कम जटिलता वाली विधियाँ मौजूद हैं,<ref name="BHR00"> | कम जटिलता वाली विधियाँ मौजूद हैं,<ref name="BHR00"> | ||
{{cite book | author = L. Bergroth and H. Hakonen and T. Raita | title = Proceedings Seventh International Symposium on String Processing and Information Retrieval. SPIRE 2000 | chapter = A survey of longest common subsequence algorithms | journal = SPIRE | year = 2000 | isbn = 0-7695-0746-8 | pages = 39–48 | doi = 10.1109/SPIRE.2000.878178 | publisher = IEEE Computer Society| s2cid = 10375334 }}</ref> | {{cite book | author = L. Bergroth and H. Hakonen and T. Raita | title = Proceedings Seventh International Symposium on String Processing and Information Retrieval. SPIRE 2000 | chapter = A survey of longest common subsequence algorithms | journal = SPIRE | year = 2000 | isbn = 0-7695-0746-8 | pages = 39–48 | doi = 10.1109/SPIRE.2000.878178 | publisher = IEEE Computer Society| s2cid = 10375334 }}</ref> | ||
जो अक्सर | जो अक्सर LCS की लंबाई, वर्णमाला के आकार या दोनों पर निर्भर करता है। | ||
LCS आवश्यक रूप से अद्वितीय नहीं है; सबसे खराब स्थिति में, इनपुट की लंबाई में सामान्य अनुवर्ती की संख्या घातीय होती है, इसलिए एल्गोरिथम जटिलता कम से कम घातीय होनी चाहिए।<ref>{{cite arXiv | author = Ronald I. Greenberg | title = सबसे लंबे सामान्य अनुवर्ती की संख्या पर सीमा| date = 2003-08-06 | eprint = cs.DM/0301030}}</ref> | |||
== दो अनुक्रमों के लिए समाधान == | == दो अनुक्रमों के लिए समाधान == | ||
LCS समस्या में एक इष्टतम उप-संरचना होती है: समस्या को छोटे, सरल उप-समस्याओं में विभाजित किया जा सकता है, जो बदले में, सरल उप-समस्याओं में विभाजित किया जा सकता है, और इसी तरह, जब तक, अंत में, समाधान तुच्छ नहीं हो जाता। LCS में विशेष रूप से ओवरलैपिंग उपसमस्याएं हैं: उच्च-स्तरीय उप-समस्याओं के समाधान अक्सर निचले स्तर की उप-समस्याओं के समाधान का पुन: उपयोग करते हैं। इन दो गुणों वाली समस्याएं गतिशील प्रोग्रामिंग दृष्टिकोण के लिए उपयुक्त हैं, जिसमें उप-समस्या समाधानों को याद किया जाता है, अर्थात, उप-समस्याओं के समाधान पुन: उपयोग के लिए सेव किये जाते हैं। | |||
=== उपसर्ग === | === उपसर्ग === | ||
| Line 40: | Line 40: | ||
=== पहली गुण === | === पहली गुण === | ||
''LCS(X^A,Y^A) = LCS(X,Y)^A,'' सभी स्ट्रिंग ''X, Y'' और सभी प्रतीकों A के लिए, जहां ^ स्ट्रिंग संयोजन को दर्शाता है। यह किसी को एक ही प्रतीक में समाप्त होने वाले दो अनुक्रमों के लिए | ''LCS(X^A,Y^A) = LCS(X,Y)^A,'' सभी स्ट्रिंग ''X, Y'' और सभी प्रतीकों A के लिए, जहां ^ स्ट्रिंग संयोजन को दर्शाता है। यह किसी को एक ही प्रतीक में समाप्त होने वाले दो अनुक्रमों के लिए ''LCS'' गणना को सरल बनाने की अनुमति देता है। उदाहरण के लिए, ''LCS''("BANANA","ATANA") = ''LCS''("BANAN","ATAN")^"A", शेष सामान्य प्रतीकों के लिए जारी रखते हुए, ''LCS''("BANANA","ATANA") = LCS(" BAN","AT")^"ANA"। | ||
=== दूसरा गुण === | === दूसरा गुण === | ||
| Line 48: | Line 48: | ||
गुण का एहसास करने के लिए, दो मामलों में अंतर करें: | गुण का एहसास करने के लिए, दो मामलों में अंतर करें: | ||
=== | यदि ''LCS''("ABCDEFG","BCDGK") "G" पर समाप्त होता है, तो अंतिम "K" ''LCS'' में नहीं हो सकता है, इसलिए ''LCS''("ABCDEFG","BCDGK") = LCS("ABCDEFG"," BCDG "). | ||
यदि ''LCS''("ABCDEFG","BCDGK") "G" पर समाप्त नहीं होता है, तो अंतिम "G" ''LCS'' में नहीं हो सकता है, इसलिए ''LCS''("ABCDEFG","BCDGK") = LCS("ABCDEF", "BCDGK")। | |||
=== ''LCS'' फ़ंक्शन परिभाषित === | |||
मान लीजिए कि दो अनुक्रमों को इस प्रकार परिभाषित किया गया है: <math>X=(x_1 x_2 \cdots x_m)</math> और <math>Y=(y_1 y_2 \cdots y_n)</math>. के उपसर्ग <math>X</math> हैं <math>X_0, X_1, X_2, \dots, X_m</math>; के उपसर्ग <math>Y</math> हैं <math>Y_0, Y_1, Y_2, \dots, Y_n</math>. होने देना <math>\mathit{LCS}(X_i,Y_j)</math> उपसर्गों के सबसे लंबे सामान्य अनुक्रम के सेट का प्रतिनिधित्व करें <math>X_i</math> और <math>Y_j</math>. अनुक्रमों का यह सेट निम्नलिखित द्वारा दिया गया है। | मान लीजिए कि दो अनुक्रमों को इस प्रकार परिभाषित किया गया है: <math>X=(x_1 x_2 \cdots x_m)</math> और <math>Y=(y_1 y_2 \cdots y_n)</math>. के उपसर्ग <math>X</math> हैं <math>X_0, X_1, X_2, \dots, X_m</math>; के उपसर्ग <math>Y</math> हैं <math>Y_0, Y_1, Y_2, \dots, Y_n</math>. होने देना <math>\mathit{LCS}(X_i,Y_j)</math> उपसर्गों के सबसे लंबे सामान्य अनुक्रम के सेट का प्रतिनिधित्व करें <math>X_i</math> और <math>Y_j</math>. अनुक्रमों का यह सेट निम्नलिखित द्वारा दिया गया है। | ||
| Line 61: | Line 63: | ||
\end{cases} | \end{cases} | ||
</math> | </math> | ||
का | का ''LCS'' खोजने के लिए <math>X_i</math> और <math>Y_j</math>, तुलना करना <math>x_i</math> और <math>y_j</math>. यदि वे बराबर हैं, तो क्रम <math>\mathit{LCS}(X_{i-1},Y_{j-1})</math> उस तत्व द्वारा विस्तारित है, <math>x_i</math>. यदि वे समान नहीं हैं, तो दोनों अनुक्रमों में से सबसे लंबा, <math>\mathit{LCS}(X_i,Y_{j-1})</math>, और <math>\mathit{LCS}(X_{i-1},Y_j)</math>, रोका गया है। (यदि उनकी लंबाई समान है, लेकिन समान नहीं है, तो दोनों को बरकरार रखा जाता है।) आधार मामला, जब दोनों में से कोई एक हो <math>X_i</math> या <math>Y_i</math> रिक्त है, <math>\epsilon</math> [[खाली स्ट्रिंग|रिक्त स्ट्रिंग]] है, . | ||
=== कार्य उदाहरण === | === कार्य उदाहरण === | ||
R = (GAC), और C = (AGCAT) का सबसे लंबा अनुवर्ती सामान्य पाया जाएगा। क्योंकि LCS फ़ंक्शन | ''R'' = (GAC), और ''C'' = (AGCAT) का सबसे लंबा अनुवर्ती सामान्य पाया जाएगा। क्योंकि ''LCS'' फ़ंक्शन "शून्य" तत्व का उपयोग करता है, इसलिए इन अनुक्रमों के लिए खाली शून्य उपसर्गों को परिभाषित करना सुविधाजनक है: ''R''<sub>0</sub> = ε; और ''C''<sub>0</sub> = ε. सभी उपसर्गों को एक तालिका में पहली पंक्ति में C (इसे एक कॉलम हेडर बनाते हुए) और पहले कॉलम में R (इसे एक row हेडर बनाते हुए) के साथ रखा गया है। | ||
{| class="wikitable" style="text-align:center" | {| class="wikitable" style="text-align:center" | ||
|+ LCS | |+ LCS स्ट्रिंग्स | ||
|- | |- | ||
! || ε || A || G || C || A || T | ! || ε || A || G || C || A || T | ||
| Line 99: | Line 101: | ||
|- | |- | ||
|} | |} | ||
इस तालिका का उपयोग गणना के प्रत्येक चरण के लिए | इस तालिका का उपयोग गणना के प्रत्येक चरण के लिए LCS अनुक्रम को संग्रहीत करने के लिए किया जाता है। दूसरे कॉलम और दूसरी पंक्ति को ε से भर दिया गया है, क्योंकि जब एक रिक्त अनुक्रम की तुलना एक गैर-रिक्त अनुक्रम से की जाती है, तो सबसे लंबा सामान्य अनुवर्ती हमेशा एक रिक्त अनुक्रम होता है। | ||
LCS(आर<sub>1</sub>, सी<sub>1</sub>) प्रत्येक अनुक्रम में पहले तत्वों की तुलना करके निर्धारित किया जाता है। जी और ए समान नहीं हैं, इसलिए इस LCS को (दूसरी गुण का उपयोग करके) दो अनुक्रमों में से सबसे लंबा LCS (आर) मिलता है<sub>1</sub>, सी<sub>0</sub>) और LCS(आर<sub>0</sub>, सी<sub>1</sub>). तालिका के अनुसार, ये दोनों रिक्त हैं, इसलिए LCS(R<sub>1</sub>, सी<sub>1</sub>) भी रिक्त है, जैसा कि नीचे दी गई तालिका में दिखाया गया है। तीर इंगित करते हैं कि अनुक्रम उपरोक्त दोनों सेल, LCS(R) से आता है<sub>0</sub>, सी<sub>1</sub>) और बाईं ओर की सेल, LCS(R<sub>1</sub>, सी<sub>0</sub>). | |||
LCS(आर<sub>1</sub>, सी<sub>2</sub>) जी और जी की तुलना करके निर्धारित किया जाता है। वे मेल खाते हैं, इसलिए जी को ऊपरी बाएँ अनुक्रम, LCS (आर) में जोड़ा जाता है<sub>0</sub>, सी<sub>1</sub>), जो (ε) है, दे रहा है (εG), जो (G) है। | |||
LCS (आर) के लिए<sub>1</sub>, सी<sub>3</sub>), G और C मेल नहीं खाते। उपरोक्त क्रम रिक्त है; बायीं ओर वाले में एक तत्व G है। इनमें से सबसे लंबे तत्व LCS(R) का चयन करें<sub>1</sub>, सी<sub>3</sub>) (जी) है. तीर बाईं ओर इंगित करता है, क्योंकि वह दो अनुक्रमों में सबसे लंबा है। | |||
LCS(आर<sub>1</sub>, सी<sub>4</sub>), इसी तरह, (जी) है। | |||
LCS(आर<sub>1</sub>, सी<sub>5</sub>), इसी तरह, (जी) है। | |||
{| class="wikitable" style="text-align:center" | {| class="wikitable" style="text-align:center" | ||
| Line 144: | Line 146: | ||
|- | |- | ||
|} | |} | ||
LCS (आर) के लिए<sub>2</sub>, सी<sub>1</sub>), ए की तुलना ए से की जाती है। दोनों तत्व मेल खाते हैं, इसलिए ए को ε में जोड़ा जाता है, जिससे (ए) मिलता है। | |||
LCS (आर) के लिए<sub>2</sub>, सी<sub>2</sub>), ए और जी मेल नहीं खाते हैं, इसलिए LCS (आर) का सबसे लंबा हिस्सा<sub>1</sub>, सी<sub>2</sub>), जो (जी) है, और LCS(आर) है<sub>2</sub>, सी<sub>1</sub>), जो (ए) है, का उपयोग किया जाता है। इस मामले में, उनमें से प्रत्येक में एक तत्व होता है, इसलिए इस LCS को दो अनुवर्ती दिए गए हैं: (ए) और (जी)। | |||
LCS (आर) के लिए<sub>2</sub>, सी<sub>3</sub>), A, C से मेल नहीं खाता है। LCS(R<sub>2</sub>, सी<sub>2</sub>) में अनुक्रम (ए) और (जी) शामिल हैं; LCS(आर<sub>1</sub>, सी<sub>3</sub>) (जी) है, जो पहले से ही LCS(आर) में समाहित है<sub>2</sub>, सी<sub>2</sub>). परिणाम यह है कि LCS(R<sub>2</sub>, सी<sub>3</sub>) में दो अनुवर्ती, (ए) और (जी) भी शामिल हैं। | |||
LCS (आर) के लिए<sub>2</sub>, सी<sub>4</sub>), ए, ए से मेल खाता है, जो ऊपरी बाएँ सेल से जुड़ा हुआ है, जो (जीए) देता है। | |||
LCS (आर) के लिए<sub>2</sub>, सी<sub>5</sub>), A, T से मेल नहीं खाता है। दो अनुक्रमों, (GA) और (G) की तुलना करने पर, सबसे लंबा (GA) है, इसलिए LCS(R)<sub>2</sub>, सी<sub>5</sub>) (GA) है. | |||
{| class="wikitable" style="text-align:center" | {| class="wikitable" style="text-align:center" | ||
| Line 187: | Line 189: | ||
|- | |- | ||
|} | |} | ||
LCS (आर) के लिए<sub>3</sub>, सी<sub>1</sub>), सी और ए मेल नहीं खाते हैं, इसलिए LCS(आर<sub>3</sub>, सी<sub>1</sub>) दो अनुक्रमों में से सबसे लंबा प्राप्त करता है, (ए)। | |||
LCS (आर) के लिए<sub>3</sub>, सी<sub>2</sub>), C और G मेल नहीं खाते। दोनों LCS(आर<sub>3</sub>, सी<sub>1</sub>) और LCS(आर<sub>2</sub>, सी<sub>2</sub>) एक तत्व है. परिणाम यह है कि LCS(R<sub>3</sub>, सी<sub>2</sub>) में दो अनुवर्ती, (ए) और (जी) शामिल हैं। | |||
LCS (आर) के लिए<sub>3</sub>, सी<sub>3</sub>), C और C मेल खाते हैं, इसलिए C को LCS(R) में जोड़ा जाता है<sub>2</sub>, सी<sub>2</sub>), जिसमें दो अनुवर्ती (ए) और (जी) शामिल हैं, जो (एसी) और (जीसी) देते हैं। | |||
LCS (आर) के लिए<sub>3</sub>, सी<sub>4</sub>), सी और ए मेल नहीं खाते। LCS(आर) का संयोजन<sub>3</sub>, सी<sub>3</sub>), जिसमें (एसी) और (जीसी), और LCS (आर) शामिल हैं<sub>2</sub>, सी<sub>4</sub>), जिसमें (जीए) शामिल है, कुल तीन अनुक्रम देता है: (एसी), (जीसी), और (जीए)। | |||
अंत में, | अंत में, LCS(आर) के लिए<sub>3</sub>, सी<sub>5</sub>), C और T मेल नहीं खाते। परिणाम यह है कि LCS(R<sub>3</sub>, सी<sub>5</sub>) में तीन अनुक्रम, (एसी), (जीसी), और (जीए) भी शामिल हैं। | ||
{| class="wikitable" style="text-align:center" | {| class="wikitable" style="text-align:center" | ||
| Line 233: | Line 235: | ||
=== ट्रेसबैक दृष्टिकोण === | === ट्रेसबैक दृष्टिकोण === | ||
LCS तालिका की एक पंक्ति के LCS की गणना के लिए केवल वर्तमान पंक्ति और पिछली पंक्ति के समाधान की आवश्यकता होती है। फिर भी, लंबे अनुक्रमों के लिए, ये क्रम असंख्य और लंबे हो सकते हैं, जिसके लिए बहुत अधिक संग्रहण स्थान की आवश्यकता होती है। भंडारण स्थान को वास्तविक अनुवर्ती को नहीं, बल्कि अनुवर्ती की लंबाई और तीरों की दिशा को सहेजकर बचाया जा सकता है, जैसा कि नीचे दी गई तालिका में है। | |||
{| class="wikitable" style="text-align:center" | {| class="wikitable" style="text-align:center" | ||
| Line 306: | Line 308: | ||
==अन्य समस्याओं से संबंध== | ==अन्य समस्याओं से संबंध== | ||
दो तारों के लिए <math>X_{1 \dots m}</math> और <math>Y_{1 \dots n}</math>, [[सबसे छोटी सामान्य सुपरसीक्वेंस समस्या]] की लंबाई | दो तारों के लिए <math>X_{1 \dots m}</math> और <math>Y_{1 \dots n}</math>, [[सबसे छोटी सामान्य सुपरसीक्वेंस समस्या]] की लंबाई LCS की लंबाई से संबंधित है<ref name="BHR00" /> | ||
:<math>\left|SCS(X,Y)\right| = n + m - \left|LCS(X,Y)\right|.</math> | :<math>\left|SCS(X,Y)\right| = n + m - \left|LCS(X,Y)\right|.</math> | ||
| Line 317: | Line 319: | ||
{{unreferenced section|date=March 2013}} | {{unreferenced section|date=March 2013}} | ||
=== | === LCS की लंबाई की गणना === | ||
नीचे दिया गया फ़ंक्शन इनपुट अनुक्रम के रूप में लेता है <code>X[1..m]</code> और <code>Y[1..n]</code>, के बीच | नीचे दिया गया फ़ंक्शन इनपुट अनुक्रम के रूप में लेता है <code>X[1..m]</code> और <code>Y[1..n]</code>, के बीच LCS की गणना करता है <code>X[1..i]</code> और <code>Y[1..j]</code> सभी के लिए <code>1 ≤ i ≤ m</code> और <code>1 ≤ j ≤ n</code>, और इसे संग्रहीत करता है <code>C[i,j]</code>. <code>C[m,n]</code> की LCS की लंबाई शामिल होगी <code>X</code> और <code>Y</code>.<ref name=":1">{{Introduction to Algorithms|3 |chapter=Dynamic Programming |pages=394}}</ref> | ||
फ़ंक्शन LCSLength(X[1..m], Y[1..n]) | फ़ंक्शन LCSLength(X[1..m], Y[1..n]) | ||
सी = सरणी(0..एम, 0..एन) | सी = सरणी(0..एम, 0..एन) | ||
| Line 359: | Line 361: | ||
=== | === LCS पढ़ना === | ||
निम्नलिखित फ़ंक्शन गणना करते समय लिए गए विकल्पों को [[बैक ट्रैकिंग]] करता है <code>C</code> मेज़। यदि उपसर्गों में अंतिम वर्ण समान हैं, तो उन्हें LCS में होना चाहिए। यदि नहीं, तो जांचें कि किस चीज़ ने रखने का सबसे बड़ा | निम्नलिखित फ़ंक्शन गणना करते समय लिए गए विकल्पों को [[बैक ट्रैकिंग]] करता है <code>C</code> मेज़। यदि उपसर्गों में अंतिम वर्ण समान हैं, तो उन्हें LCS में होना चाहिए। यदि नहीं, तो जांचें कि किस चीज़ ने रखने का सबसे बड़ा LCS दिया <math>x_i</math> और <math>y_j</math>, और वही चुनाव करें। यदि वे समान रूप से लंबे हों तो बस एक चुनें। फ़ंक्शन को कॉल करें <code>i=m</code> और <code>j=n</code>. | ||
फ़ंक्शन बैकट्रैक (C[0..m,0..n], X[1..m], Y[1..n], i, j) | फ़ंक्शन बैकट्रैक (C[0..m,0..n], X[1..m], Y[1..n], i, j) | ||
| Line 386: | Line 388: | ||
=== सभी | === सभी LCS को पढ़ना === | ||
अगर चुन रहे हैं <math>x_i</math> और <math>y_j</math> समान रूप से लंबा परिणाम देगा, दोनों परिणामी अनुवर्ती पढ़ें। इसे इस फ़ंक्शन द्वारा एक सेट के रूप में लौटाया जाता है। ध्यान दें कि यह फ़ंक्शन बहुपद नहीं है, क्योंकि यदि तार समान हैं तो यह लगभग हर चरण में शाखाबद्ध हो सकता है। | अगर चुन रहे हैं <math>x_i</math> और <math>y_j</math> समान रूप से लंबा परिणाम देगा, दोनों परिणामी अनुवर्ती पढ़ें। इसे इस फ़ंक्शन द्वारा एक सेट के रूप में लौटाया जाता है। ध्यान दें कि यह फ़ंक्शन बहुपद नहीं है, क्योंकि यदि तार समान हैं तो यह लगभग हर चरण में शाखाबद्ध हो सकता है। | ||
| Line 418: | Line 420: | ||
=== उदाहरण === | === उदाहरण === | ||
होने देना <math>X</math> होना "<code>XMJYAUZ</code>" और <math>Y</math> होना "<code>MZJAWXU</code>”। के बीच सबसे लंबा सामान्य अनुवर्ती <math>X</math> और <math>Y</math> है "<code>MJAU</code>”। टेबल <code>C</code> नीचे दिखाया गया है, जो फ़ंक्शन द्वारा उत्पन्न होता है <code>LCSLength</code>, के उपसर्गों के बीच सबसे लंबे सामान्य अनुवर्ती की लंबाई दिखाता है <math>X</math> और <math>Y</math>. <math>i</math>वें>वें पंक्ति और <math>j</math>वां कॉलम बीच में | होने देना <math>X</math> होना "<code>XMJYAUZ</code>" और <math>Y</math> होना "<code>MZJAWXU</code>”। के बीच सबसे लंबा सामान्य अनुवर्ती <math>X</math> और <math>Y</math> है "<code>MJAU</code>”। टेबल <code>C</code> नीचे दिखाया गया है, जो फ़ंक्शन द्वारा उत्पन्न होता है <code>LCSLength</code>, के उपसर्गों के बीच सबसे लंबे सामान्य अनुवर्ती की लंबाई दिखाता है <math>X</math> और <math>Y</math>. <math>i</math>वें>वें पंक्ति और <math>j</math>वां कॉलम बीच में LCS की लंबाई दिखाता है <math>X_{1..i}</math> और <math>Y_{1..j}</math>. | ||
{| class="wikitable" style="text-align: center;" | {| class="wikitable" style="text-align: center;" | ||
| Line 451: | Line 453: | ||
| 0 || 1 || 2 || 2 || 3 || 3 || 3 || style="background: yellow" | 4 | | 0 || 1 || 2 || 2 || 3 || 3 || 3 || style="background: yellow" | 4 | ||
|} | |} | ||
<span style= बैकग्राउंड: पीला >हाइलाइट</span> नंबर फ़ंक्शन का पथ दिखाते हैं <code>backtrack</code> | <span style= बैकग्राउंड: पीला >हाइलाइट</span> नंबर फ़ंक्शन का पथ दिखाते हैं <code>backtrack</code> LCS पढ़ते समय, नीचे दाएं से ऊपरी बाएं कोने तक चलेगा। यदि वर्तमान प्रतीकों में <math>X</math> और <math>Y</math> बराबर हैं, वे LCS का हिस्सा हैं, और हम ऊपर और बाएं दोनों तरफ जाते हैं (बोल्ड में दिखाया गया है)। यदि नहीं, तो हम ऊपर या बाएँ जाते हैं, यह इस बात पर निर्भर करता है कि किस सेल की संख्या अधिक है। यह या तो LCS को बीच में लेने से मेल खाता है <math>X_{1..i-1}</math> और <math>Y_{1..j}</math>, या <math>X_{1..i}</math> और <math>Y_{1..j-1}</math>. | ||
== कोड अनुकूलन == | == कोड अनुकूलन == | ||
| Line 489: | Line 491: | ||
=== आवश्यक स्थान कम करें === | === आवश्यक स्थान कम करें === | ||
यदि केवल | यदि केवल LCS की लंबाई की आवश्यकता है, तो मैट्रिक्स को कम किया जा सकता है <math>2\times \min(n,m)</math> मैट्रिक्स, या करने के लिए एक <math>\min(m,n)+1</math> गतिशील प्रोग्रामिंग दृष्टिकोण के रूप में वेक्टर को मैट्रिक्स के केवल वर्तमान और पिछले कॉलम की आवश्यकता होती है। हिर्शबर्ग का एल्गोरिदम समान द्विघात समय और रैखिक स्थान सीमा में ही इष्टतम अनुक्रम के निर्माण की अनुमति देता है।<ref>{{cite journal|author-link = Dan Hirschberg|author=Hirschberg, D. S.|title=अधिकतम सामान्य अनुवर्ती की गणना के लिए एक रैखिक अंतरिक्ष एल्गोरिदम|journal=Communications of the ACM|volume=18|issue=6|year=1975|pages=341–343|doi=10.1145/360825.360861|s2cid=207694727}}</ref> | ||
=== कैश छूट को कम करें === | === कैश छूट को कम करें === | ||
चौधरी और रामचंद्रन ने एक द्विघात-समय रैखिक-अंतरिक्ष एल्गोरिदम तैयार किया<ref name="CR-06" /><ref name="CLR-08">{{cite journal |last1=Chowdhury |first1=Rezaul |last2=Le |first2=Hai-Son |last3=Ramachandran |first3=Vijaya |title=जैव सूचना विज्ञान के लिए कैश-विस्मृत गतिशील प्रोग्रामिंग|journal=IEEE/ACM Transactions on Computational Biology and Bioinformatics (TCBB) |date=July 2010 |volume=7 |issue=3 |pages=495–510 |doi=10.1109/TCBB.2008.94 |pmid=20671320 |s2cid=2532039 |url=https://ieeexplore.ieee.org/document/4609376}}</ref> एक इष्टतम अनुक्रम के साथ | चौधरी और रामचंद्रन ने एक द्विघात-समय रैखिक-अंतरिक्ष एल्गोरिदम तैयार किया<ref name="CR-06" /><ref name="CLR-08">{{cite journal |last1=Chowdhury |first1=Rezaul |last2=Le |first2=Hai-Son |last3=Ramachandran |first3=Vijaya |title=जैव सूचना विज्ञान के लिए कैश-विस्मृत गतिशील प्रोग्रामिंग|journal=IEEE/ACM Transactions on Computational Biology and Bioinformatics (TCBB) |date=July 2010 |volume=7 |issue=3 |pages=495–510 |doi=10.1109/TCBB.2008.94 |pmid=20671320 |s2cid=2532039 |url=https://ieeexplore.ieee.org/document/4609376}}</ref> एक इष्टतम अनुक्रम के साथ LCS लंबाई खोजने के लिए जो अपने बेहतर कैश प्रदर्शन के कारण व्यवहार में हिर्शबर्ग के एल्गोरिदम से तेज़ चलता है।<ref name="CR-06">{{cite journal |last1=Chowdhury |first1=Rezaul |last2=Ramachandran |first2=Vijaya |title=कैश-विस्मृत गतिशील प्रोग्रामिंग|journal=Proceedings of the Seventeenth Annual ACM-SIAM Symposium on Discrete Algorithm (SODA) |date=January 2006 |pages=591–600 |doi=10.1145/1109557.1109622 |isbn=0898716055 |s2cid=9650418 |url=https://dl.acm.org/doi/10.5555/1109557.1109622}}</ref> कैश-ओब्लिवियस#आदर्शीकृत कैश मॉडल के तहत एल्गोरिदम में एक असम्बद्ध रूप से इष्टतम कैश जटिलता है।<ref name="FLPR-12">{{cite journal |last1=Frigo |first1=Matteo |last2=Leiserson |first2=Charles E. |last3=Prokop |first3=Harald |last4=Ramachandran |first4=Sridhar |title=कैश-विस्मृत एल्गोरिदम|journal=ACM Transactions on Algorithms |date=January 2012 |volume=8 |issue=1 |pages=1–22 |doi=10.1145/2071379.2071383 |url=https://dl.acm.org/doi/10.1145/2071379.2071383}}</ref> दिलचस्प बात यह है कि एल्गोरिथ्म स्वयं [[कैश-अनभिज्ञ]] है<ref name="FLPR-12" />इसका मतलब यह है कि यह मशीन के कैश पैरामीटर (उदाहरण के लिए, कैश आकार और कैश लाइन आकार) के आधार पर कोई विकल्प नहीं बनाता है। | ||
=== आगे अनुकूलित एल्गोरिदम === | === आगे अनुकूलित एल्गोरिदम === | ||
| Line 520: | Line 522: | ||
| title = Longest common subsequences of two random sequences | | title = Longest common subsequences of two random sequences | ||
| volume = 12 | | volume = 12 | ||
| issue = 2 | year = 1975 | doi=10.2307/3212444| jstor = 3212444 | s2cid = 250345191 }}.</ref> कई शोधकर्ताओं ने सबसे लंबी सामान्य अनुवर्ती लंबाई के व्यवहार की जांच की है जब दो दिए गए तार एक ही वर्णमाला से यादृच्छिक रूप से खींचे जाते हैं। जब वर्णमाला का आकार स्थिर होता है, तो | | issue = 2 | year = 1975 | doi=10.2307/3212444| jstor = 3212444 | s2cid = 250345191 }}.</ref> कई शोधकर्ताओं ने सबसे लंबी सामान्य अनुवर्ती लंबाई के व्यवहार की जांच की है जब दो दिए गए तार एक ही वर्णमाला से यादृच्छिक रूप से खींचे जाते हैं। जब वर्णमाला का आकार स्थिर होता है, तो LCS की अपेक्षित लंबाई दो तारों की लंबाई के समानुपाती होती है, और आनुपातिकता के स्थिरांक (वर्णमाला के आकार के आधार पर) च्वाटल-सैंकॉफ स्थिरांक के रूप में जाने जाते हैं। उनके सटीक मूल्य ज्ञात नहीं हैं, लेकिन उनके मूल्यों की ऊपरी और निचली सीमाएं सिद्ध हो चुकी हैं,<ref>{{citation | ||
| last = Lueker | first = George S. | | last = Lueker | first = George S. | ||
| doi = 10.1145/1516512.1516519 | | doi = 10.1145/1516512.1516519 | ||
Revision as of 23:07, 7 August 2023
सबसे लंबा सामान्य अनुवर्ती (LCS) अनुक्रमों के एक सेट (अक्सर केवल दो अनुक्रम) में सभी अनुक्रमों के लिए सामान्य सबसे लंबा अनुवर्ती है। यह सबसे लंबे सामान्य सबस्ट्रिंग से भिन्न है: सबस्ट्रिंग के विपरीत, बाद के अनुक्रमों को मूल अनुक्रमों के भीतर लगातार पदों पर रहने की आवश्यकता नहीं होती है। सबसे लंबे समय तक सामान्य अनुक्रमों की गणना करने की समस्या एक क्लासिक कंप्यूटर विज्ञान समस्या है, जो अंतर उपयोगिता जैसे डेटा तुलना कार्यक्रमों का आधार है, diffऔर कम्प्यूटेशनल भाषाविज्ञान और जैव सूचना विज्ञान में इसका अनुप्रयोग है। फ़ाइलों के संशोधन-नियंत्रित संग्रह में किए गए कई परिवर्तनों को समेटने के लिए Git जैसी संशोधन नियंत्रण प्रणालियों द्वारा भी इसका व्यापक रूप से उपयोग किया जाता है।
उदाहरण के लिए, अनुक्रमों (ABCD) और (ACBAD) पर विचार करें। उनकी 5 लंबाई-2 सामान्य अनुवर्ती हैं: (AB), (AC), (AD), (BD), और (CD); 2 लंबाई-3 सामान्य अनुवर्ती: (ABD) और (ACD); और अब कोई सामान्य अनुवर्ती नहीं है। अतः (ABD) और (ACD) उनके सबसे लंबे सामान्य अनुवर्ती हैं।
जटिलता
इनपुट अनुक्रमों की यादृच्छिक संख्या के सामान्य मामले के लिए, समस्या एनपी-हार्ड है।[1] जब अनुक्रमों की संख्या स्थिर होती है, तो समस्या को गतिशील प्रोग्रामिंग द्वारा बहुपद समय में हल किया जा सकता है।
दिया गया लंबाई का क्रम , एक अनुभवहीन खोज प्रत्येक का परीक्षण करेगी पहले अनुक्रम के अनुवर्ती यह निर्धारित करने के लिए कि क्या वे शेष अनुक्रमों के भी अनुवर्ती हैं; प्रत्येक अनुवर्ती को शेष अनुक्रमों की लंबाई में रैखिक समय में परीक्षण किया जा सकता है, इसलिए इस एल्गोरिदम के लिए समय होगा
n और m तत्वों के दो अनुक्रमों के मामले में, गतिशील प्रोग्रामिंग दृष्टिकोण का चलने का समय O(n × m) है।[2] इनपुट अनुक्रमों की एक मनमाने ढंग से संख्या के लिए, गतिशील प्रोग्रामिंग दृष्टिकोण एक समाधान देता है
कम जटिलता वाली विधियाँ मौजूद हैं,[3] जो अक्सर LCS की लंबाई, वर्णमाला के आकार या दोनों पर निर्भर करता है।
LCS आवश्यक रूप से अद्वितीय नहीं है; सबसे खराब स्थिति में, इनपुट की लंबाई में सामान्य अनुवर्ती की संख्या घातीय होती है, इसलिए एल्गोरिथम जटिलता कम से कम घातीय होनी चाहिए।[4]
दो अनुक्रमों के लिए समाधान
LCS समस्या में एक इष्टतम उप-संरचना होती है: समस्या को छोटे, सरल उप-समस्याओं में विभाजित किया जा सकता है, जो बदले में, सरल उप-समस्याओं में विभाजित किया जा सकता है, और इसी तरह, जब तक, अंत में, समाधान तुच्छ नहीं हो जाता। LCS में विशेष रूप से ओवरलैपिंग उपसमस्याएं हैं: उच्च-स्तरीय उप-समस्याओं के समाधान अक्सर निचले स्तर की उप-समस्याओं के समाधान का पुन: उपयोग करते हैं। इन दो गुणों वाली समस्याएं गतिशील प्रोग्रामिंग दृष्टिकोण के लिए उपयुक्त हैं, जिसमें उप-समस्या समाधानों को याद किया जाता है, अर्थात, उप-समस्याओं के समाधान पुन: उपयोग के लिए सेव किये जाते हैं।
उपसर्ग
S के उपसर्ग Sn को S के पहले n वर्णों के रूप में परिभाषित किया गया है।[5] उदाहरण के लिए, S=(AGCA) के उपसर्ग हैं।
- S0 = ()
- S1 = (A)
- S2 = (AG)
- S3 = (AGC)
- S4 = (AGCA).
मान लें कि LCS(X, Y) एक ऐसा फ़ंक्शन है जो X और Y के लिए सामान्य सबसे लंबे अनुवर्ती की गणना करता है। ऐसे फ़ंक्शन में दो रोचक गुण होते हैं।
पहली गुण
LCS(X^A,Y^A) = LCS(X,Y)^A, सभी स्ट्रिंग X, Y और सभी प्रतीकों A के लिए, जहां ^ स्ट्रिंग संयोजन को दर्शाता है। यह किसी को एक ही प्रतीक में समाप्त होने वाले दो अनुक्रमों के लिए LCS गणना को सरल बनाने की अनुमति देता है। उदाहरण के लिए, LCS("BANANA","ATANA") = LCS("BANAN","ATAN")^"A", शेष सामान्य प्रतीकों के लिए जारी रखते हुए, LCS("BANANA","ATANA") = LCS(" BAN","AT")^"ANA"।
दूसरा गुण
यदि A और B अलग-अलग प्रतीक (A≠B) हैं, तो LCS(X^A,Y^B) सेट { LCS(X^A,Y), LCS(X,Y^B) } में अधिकतम लंबाई वाली स्ट्रिंग में से एक है, सभी स्ट्रिंग्स X, Y के लिए।
उदाहरण के लिए, LCS("ABCDEFG","BCDGK") LCS("ABCDEFG","BCDG") और LCS("ABCDEF","BCDGK") के बीच सबसे लंबी स्ट्रिंग है; यदि दोनों की लंबाई समान हो तो उनमें से किसी एक को मनमाने ढंग से चुना जा सकता है।
गुण का एहसास करने के लिए, दो मामलों में अंतर करें:
यदि LCS("ABCDEFG","BCDGK") "G" पर समाप्त होता है, तो अंतिम "K" LCS में नहीं हो सकता है, इसलिए LCS("ABCDEFG","BCDGK") = LCS("ABCDEFG"," BCDG ").
यदि LCS("ABCDEFG","BCDGK") "G" पर समाप्त नहीं होता है, तो अंतिम "G" LCS में नहीं हो सकता है, इसलिए LCS("ABCDEFG","BCDGK") = LCS("ABCDEF", "BCDGK")।
LCS फ़ंक्शन परिभाषित
मान लीजिए कि दो अनुक्रमों को इस प्रकार परिभाषित किया गया है: और . के उपसर्ग हैं ; के उपसर्ग हैं . होने देना उपसर्गों के सबसे लंबे सामान्य अनुक्रम के सेट का प्रतिनिधित्व करें और . अनुक्रमों का यह सेट निम्नलिखित द्वारा दिया गया है।
का LCS खोजने के लिए और , तुलना करना और . यदि वे बराबर हैं, तो क्रम उस तत्व द्वारा विस्तारित है, . यदि वे समान नहीं हैं, तो दोनों अनुक्रमों में से सबसे लंबा, , और , रोका गया है। (यदि उनकी लंबाई समान है, लेकिन समान नहीं है, तो दोनों को बरकरार रखा जाता है।) आधार मामला, जब दोनों में से कोई एक हो या रिक्त है, रिक्त स्ट्रिंग है, .
कार्य उदाहरण
R = (GAC), और C = (AGCAT) का सबसे लंबा अनुवर्ती सामान्य पाया जाएगा। क्योंकि LCS फ़ंक्शन "शून्य" तत्व का उपयोग करता है, इसलिए इन अनुक्रमों के लिए खाली शून्य उपसर्गों को परिभाषित करना सुविधाजनक है: R0 = ε; और C0 = ε. सभी उपसर्गों को एक तालिका में पहली पंक्ति में C (इसे एक कॉलम हेडर बनाते हुए) और पहले कॉलम में R (इसे एक row हेडर बनाते हुए) के साथ रखा गया है।
| ε | A | G | C | A | T | |
|---|---|---|---|---|---|---|
| ε | ε | ε | ε | ε | ε | ε |
| G | ε | |||||
| A | ε | |||||
| C | ε |
इस तालिका का उपयोग गणना के प्रत्येक चरण के लिए LCS अनुक्रम को संग्रहीत करने के लिए किया जाता है। दूसरे कॉलम और दूसरी पंक्ति को ε से भर दिया गया है, क्योंकि जब एक रिक्त अनुक्रम की तुलना एक गैर-रिक्त अनुक्रम से की जाती है, तो सबसे लंबा सामान्य अनुवर्ती हमेशा एक रिक्त अनुक्रम होता है।
LCS(आर1, सी1) प्रत्येक अनुक्रम में पहले तत्वों की तुलना करके निर्धारित किया जाता है। जी और ए समान नहीं हैं, इसलिए इस LCS को (दूसरी गुण का उपयोग करके) दो अनुक्रमों में से सबसे लंबा LCS (आर) मिलता है1, सी0) और LCS(आर0, सी1). तालिका के अनुसार, ये दोनों रिक्त हैं, इसलिए LCS(R1, सी1) भी रिक्त है, जैसा कि नीचे दी गई तालिका में दिखाया गया है। तीर इंगित करते हैं कि अनुक्रम उपरोक्त दोनों सेल, LCS(R) से आता है0, सी1) और बाईं ओर की सेल, LCS(R1, सी0).
LCS(आर1, सी2) जी और जी की तुलना करके निर्धारित किया जाता है। वे मेल खाते हैं, इसलिए जी को ऊपरी बाएँ अनुक्रम, LCS (आर) में जोड़ा जाता है0, सी1), जो (ε) है, दे रहा है (εG), जो (G) है।
LCS (आर) के लिए1, सी3), G और C मेल नहीं खाते। उपरोक्त क्रम रिक्त है; बायीं ओर वाले में एक तत्व G है। इनमें से सबसे लंबे तत्व LCS(R) का चयन करें1, सी3) (जी) है. तीर बाईं ओर इंगित करता है, क्योंकि वह दो अनुक्रमों में सबसे लंबा है।
LCS(आर1, सी4), इसी तरह, (जी) है।
LCS(आर1, सी5), इसी तरह, (जी) है।
| ε | A | G | C | A | T | |
|---|---|---|---|---|---|---|
| ε | ε | ε | ε | ε | ε | ε |
| G | ε | ε | (G) | (G) | (G) | (G) |
| A | ε | |||||
| C | ε |
LCS (आर) के लिए2, सी1), ए की तुलना ए से की जाती है। दोनों तत्व मेल खाते हैं, इसलिए ए को ε में जोड़ा जाता है, जिससे (ए) मिलता है।
LCS (आर) के लिए2, सी2), ए और जी मेल नहीं खाते हैं, इसलिए LCS (आर) का सबसे लंबा हिस्सा1, सी2), जो (जी) है, और LCS(आर) है2, सी1), जो (ए) है, का उपयोग किया जाता है। इस मामले में, उनमें से प्रत्येक में एक तत्व होता है, इसलिए इस LCS को दो अनुवर्ती दिए गए हैं: (ए) और (जी)।
LCS (आर) के लिए2, सी3), A, C से मेल नहीं खाता है। LCS(R2, सी2) में अनुक्रम (ए) और (जी) शामिल हैं; LCS(आर1, सी3) (जी) है, जो पहले से ही LCS(आर) में समाहित है2, सी2). परिणाम यह है कि LCS(R2, सी3) में दो अनुवर्ती, (ए) और (जी) भी शामिल हैं।
LCS (आर) के लिए2, सी4), ए, ए से मेल खाता है, जो ऊपरी बाएँ सेल से जुड़ा हुआ है, जो (जीए) देता है।
LCS (आर) के लिए2, सी5), A, T से मेल नहीं खाता है। दो अनुक्रमों, (GA) और (G) की तुलना करने पर, सबसे लंबा (GA) है, इसलिए LCS(R)2, सी5) (GA) है.
| ε | A | G | C | A | T | |
|---|---|---|---|---|---|---|
| ε | ε | ε | ε | ε | ε | ε |
| G | ε | ε | (G) | (G) | (G) | (G) |
| A | ε | (A) | (A) & (G) | (A) & (G) | (GA) | (GA) |
| C | ε |
LCS (आर) के लिए3, सी1), सी और ए मेल नहीं खाते हैं, इसलिए LCS(आर3, सी1) दो अनुक्रमों में से सबसे लंबा प्राप्त करता है, (ए)।
LCS (आर) के लिए3, सी2), C और G मेल नहीं खाते। दोनों LCS(आर3, सी1) और LCS(आर2, सी2) एक तत्व है. परिणाम यह है कि LCS(R3, सी2) में दो अनुवर्ती, (ए) और (जी) शामिल हैं।
LCS (आर) के लिए3, सी3), C और C मेल खाते हैं, इसलिए C को LCS(R) में जोड़ा जाता है2, सी2), जिसमें दो अनुवर्ती (ए) और (जी) शामिल हैं, जो (एसी) और (जीसी) देते हैं।
LCS (आर) के लिए3, सी4), सी और ए मेल नहीं खाते। LCS(आर) का संयोजन3, सी3), जिसमें (एसी) और (जीसी), और LCS (आर) शामिल हैं2, सी4), जिसमें (जीए) शामिल है, कुल तीन अनुक्रम देता है: (एसी), (जीसी), और (जीए)।
अंत में, LCS(आर) के लिए3, सी5), C और T मेल नहीं खाते। परिणाम यह है कि LCS(R3, सी5) में तीन अनुक्रम, (एसी), (जीसी), और (जीए) भी शामिल हैं।
| ε | A | G | C | A | T | |
|---|---|---|---|---|---|---|
| ε | ε | ε | ε | ε | ε | ε |
| G | ε | ε | (G) | (G) | (G) | (G) |
| A | ε | (A) | (A) & (G) | (A) & (G) | (GA) | (GA) |
| C | ε | (A) | (A) & (G) | (AC) & (GC) | (AC) & (GC) & (GA) | (AC) & (GC) & (GA) |
अंतिम परिणाम यह है कि अंतिम सेल में (एजीसीएटी) और (जीएसी) के सभी सबसे लंबे अनुवर्ती सामान्य शामिल हैं; ये हैं (एसी), (जीसी), और (जीए)। तालिका उपसर्गों की प्रत्येक संभावित जोड़ी के लिए सबसे लंबे समय तक सामान्य अनुवर्ती भी दिखाती है। उदाहरण के लिए, (एजीसी) और (जीए) के लिए, सबसे लंबे सामान्य अनुवर्ती (ए) और (जी) हैं।
ट्रेसबैक दृष्टिकोण
LCS तालिका की एक पंक्ति के LCS की गणना के लिए केवल वर्तमान पंक्ति और पिछली पंक्ति के समाधान की आवश्यकता होती है। फिर भी, लंबे अनुक्रमों के लिए, ये क्रम असंख्य और लंबे हो सकते हैं, जिसके लिए बहुत अधिक संग्रहण स्थान की आवश्यकता होती है। भंडारण स्थान को वास्तविक अनुवर्ती को नहीं, बल्कि अनुवर्ती की लंबाई और तीरों की दिशा को सहेजकर बचाया जा सकता है, जैसा कि नीचे दी गई तालिका में है।
| ε | A | G | C | A | T | |
|---|---|---|---|---|---|---|
| ε | 0 | 0 | 0 | 0 | 0 | 0 |
| G | 0 | 0 | 1 | 1 | 1 | 1 |
| A | 0 | 1 | 1 | 1 | 2 | 2 |
| C | 0 | 1 | 1 | 2 | 2 | 2 |
वास्तविक अनुवर्ती ट्रेसबैक प्रक्रिया में निकाले जाते हैं जो तालिका में अंतिम सेल से शुरू होकर पीछे की ओर तीरों का अनुसरण करती है। जब लंबाई घटती है, तो अनुक्रमों में एक सामान्य तत्व होना चाहिए। जब एक सेल में दो तीर दिखाए जाते हैं तो कई पथ संभव होते हैं। नीचे इस तरह के विश्लेषण के लिए तालिका दी गई है, जिसमें उन कोशिकाओं में रंगीन संख्याएं हैं जहां लंबाई घटने वाली है। बोल्ड संख्याएँ अनुक्रम (जीए) का पता लगाती हैं।[6]
| ε | A | G | C | A | T | |
|---|---|---|---|---|---|---|
| ε | 0 | 0 | 0 | 0 | 0 | 0 |
| G | 0 | 0 | 1 | 1 | 1 | 1 |
| A | 0 | 1 | 1 | 1 | 2 | 2 |
| C | 0 | 1 | 1 | 2 | 2 | 2 |
अन्य समस्याओं से संबंध
दो तारों के लिए और , सबसे छोटी सामान्य सुपरसीक्वेंस समस्या की लंबाई LCS की लंबाई से संबंधित है[3]
जब केवल सम्मिलन और विलोपन की अनुमति है (कोई प्रतिस्थापन नहीं), या जब प्रतिस्थापन की लागत सम्मिलन या विलोपन की लागत से दोगुनी है, तो संपादन दूरी है:
गतिशील प्रोग्रामिंग समाधान के लिए कोड
This section does not cite any sources. (March 2013) (Learn how and when to remove this template message) |
LCS की लंबाई की गणना
नीचे दिया गया फ़ंक्शन इनपुट अनुक्रम के रूप में लेता है X[1..m] और Y[1..n], के बीच LCS की गणना करता है X[1..i] और Y[1..j] सभी के लिए 1 ≤ i ≤ m और 1 ≤ j ≤ n, और इसे संग्रहीत करता है C[i,j]. C[m,n] की LCS की लंबाई शामिल होगी X और Y.[7]
फ़ंक्शन LCSLength(X[1..m], Y[1..n])
सी = सरणी(0..एम, 0..एन)
i के लिए := 0..m
सी[i,0] = 0
j के लिए := 0..n
सी[0,जे] = 0
मेरे लिए := 1..मी
j के लिए := 1..n
यदि X[i] = Y[j]
सी[आई,जे] := सी[आई-1,जे-1] + 1
अन्य
सी[आई,जे] := अधिकतम(सी[आई,जे-1], सी[आई-1,जे])
वापसी सी[एम,एन]
वैकल्पिक रूप से, संस्मरण का उपयोग किया जा सकता है।
====सी#==== में उदाहरण
static int LcsLength(string a, string b)
{
int m = a.Length;
int n = b.Length;
int[,] C = new int[m + 1, n + 1];
for (int i = 0; i <= m; i++)
C[i, 0] = 0;
for (int j = 0; j <= n; j++)
C[0, j] = 0;
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++)
{
if (a[i - 1] == b[j - 1])
C[i, j] = C[i - 1, j - 1] + 1;
else
C[i, j] = Math.Max(C[i, j - 1], C[i - 1, j]);
}
return C[m, n];
}
LCS पढ़ना
निम्नलिखित फ़ंक्शन गणना करते समय लिए गए विकल्पों को बैक ट्रैकिंग करता है C मेज़। यदि उपसर्गों में अंतिम वर्ण समान हैं, तो उन्हें LCS में होना चाहिए। यदि नहीं, तो जांचें कि किस चीज़ ने रखने का सबसे बड़ा LCS दिया और , और वही चुनाव करें। यदि वे समान रूप से लंबे हों तो बस एक चुनें। फ़ंक्शन को कॉल करें i=m और j=n.
फ़ंक्शन बैकट्रैक (C[0..m,0..n], X[1..m], Y[1..n], i, j)
यदि मैं = 0 या जे = 0
वापस करना
यदि X[i] = Y[j]
बैकट्रैक लौटें (सी, एक्स, वाई, आई-1, जे-1) + एक्स[आई]
यदि C[i,j-1] > C[i-1,j]
बैकट्रैक लौटें (सी, एक्स, वाई, आई, जे-1)
बैकट्रैक लौटें (सी, एक्स, वाई, आई-1, जे)
====सी#==== में उदाहरण
string backtrack(int[,] C, char[] aStr, char[] bStr, int x, int y)
{
if (x == 0 | y == 0)
return "";
if (aStr[x - 1] == bStr[y - 1]) // x-1, y-1
return backtrack(C, aStr, bStr, x - 1, y - 1) + aStr[x - 1]; // x-1
if (C[x, y - 1] > C[x - 1, y])
return backtrack(C, aStr, bStr, x, y - 1);
return backtrack(C, aStr, bStr, x - 1, y);
}
सभी LCS को पढ़ना
अगर चुन रहे हैं और समान रूप से लंबा परिणाम देगा, दोनों परिणामी अनुवर्ती पढ़ें। इसे इस फ़ंक्शन द्वारा एक सेट के रूप में लौटाया जाता है। ध्यान दें कि यह फ़ंक्शन बहुपद नहीं है, क्योंकि यदि तार समान हैं तो यह लगभग हर चरण में शाखाबद्ध हो सकता है।
फ़ंक्शन बैकट्रैकऑल(C[0..m,0..n], X[1..m], Y[1..n], i, j)
यदि मैं = 0 या जे = 0
वापस करना { }
यदि X[i] = Y[j]
बैकट्रैकऑल में सभी Z के लिए {Z + X[i] लौटाएं(C, X, Y, i-1, j-1)}
आर := {}
यदि C[i,j-1] ≥ C[i-1,j]
आर := बैकट्रैकऑल(सी, एक्स, वाई, आई, जे-1)
यदि C[i-1,j] ≥ C[i,j-1]
आर := आर ∪ बैकट्रैकऑल(सी, एक्स, वाई, आई-1, जे)
वापसी आर
अंतर प्रिंट करें
यह फ़ंक्शन सी मैट्रिक्स के माध्यम से बैकट्रैक करेगा, और दो अनुक्रमों के बीच अंतर को प्रिंट करेगा। ध्यान दें कि यदि आप आदान-प्रदान करते हैं तो आपको एक अलग उत्तर मिलेगा ≥ और <, साथ > और ≤ नीचे।
फ़ंक्शन printDiff(C[0..m,0..n], X[1..m], Y[1..n], i, j)
यदि i >= 0 और j >= 0 और X[i] = Y[j]
प्रिंटडिफ (सी, एक्स, वाई, आई-1, जे-1)
प्रिंट + एक्स[i]
अन्यथा यदि j > 0 और (i = 0 या C[i,j-1] ≥ C[i-1,j])
प्रिंटडिफ (सी, एक्स, वाई, आई, जे-1)
प्रिंट + + वाई[जे]
अन्यथा यदि i > 0 और (j = 0 या C[i,j-1] < C[i-1,j])
प्रिंटडिफ (सी, एक्स, वाई, आई-1, जे)
प्रिंट - + एक्स[i]
अन्य
छपाई
उदाहरण
होने देना होना "XMJYAUZ" और होना "MZJAWXU”। के बीच सबसे लंबा सामान्य अनुवर्ती और है "MJAU”। टेबल C नीचे दिखाया गया है, जो फ़ंक्शन द्वारा उत्पन्न होता है LCSLength, के उपसर्गों के बीच सबसे लंबे सामान्य अनुवर्ती की लंबाई दिखाता है और . वें>वें पंक्ति और वां कॉलम बीच में LCS की लंबाई दिखाता है और .
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ||
|---|---|---|---|---|---|---|---|---|---|
| ε | M | Z | J | A | W | X | U | ||
| 0 | ε | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | X | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
| 2 | M | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| 3 | J | 0 | 1 | 1 | 2 | 2 | 2 | 2 | 2 |
| 4 | Y | 0 | 1 | 1 | 2 | 2 | 2 | 2 | 2 |
| 5 | A | 0 | 1 | 1 | 2 | 3 | 3 | 3 | 3 |
| 6 | U | 0 | 1 | 1 | 2 | 3 | 3 | 3 | 4 |
| 7 | Z | 0 | 1 | 2 | 2 | 3 | 3 | 3 | 4 |
हाइलाइट नंबर फ़ंक्शन का पथ दिखाते हैं backtrack LCS पढ़ते समय, नीचे दाएं से ऊपरी बाएं कोने तक चलेगा। यदि वर्तमान प्रतीकों में और बराबर हैं, वे LCS का हिस्सा हैं, और हम ऊपर और बाएं दोनों तरफ जाते हैं (बोल्ड में दिखाया गया है)। यदि नहीं, तो हम ऊपर या बाएँ जाते हैं, यह इस बात पर निर्भर करता है कि किस सेल की संख्या अधिक है। यह या तो LCS को बीच में लेने से मेल खाता है और , या और .
कोड अनुकूलन
वास्तविक दुनिया के मामलों के लिए इसे तेज़ करने के लिए उपरोक्त एल्गोरिदम में कई अनुकूलन किए जा सकते हैं।
समस्या सेट कम करें
अनुभवहीन एल्गोरिथ्म में सी मैट्रिक्स अनुक्रमों की लंबाई के साथ द्विघात वृद्धि। दो 100-आइटम अनुक्रमों के लिए, 10,000-आइटम मैट्रिक्स की आवश्यकता होगी, और 10,000 तुलनाएँ करने की आवश्यकता होगी। अधिकांश वास्तविक दुनिया के मामलों में, विशेष रूप से स्रोत कोड अंतर और पैच में, फ़ाइलों की शुरुआत और अंत शायद ही कभी बदलते हैं, और लगभग निश्चित रूप से एक ही समय में दोनों नहीं। यदि अनुक्रम के बीच में केवल कुछ आइटम बदले गए हैं, तो शुरुआत और अंत को हटाया जा सकता है। इससे न केवल मैट्रिक्स के लिए मेमोरी आवश्यकताएं कम हो जाती हैं, बल्कि तुलनाओं की संख्या भी कम हो जाती है।
फ़ंक्शन LCS(X[1..m], Y[1..n])
प्रारंभ := 1
m_end := m
n_end := n
शुरुआत में मेल खाने वाली वस्तुओं को काट दें
जबकि प्रारंभ ≤ m_end और प्रारंभ ≤ n_end और X[प्रारंभ] = Y[प्रारंभ]
प्रारंभ := प्रारंभ + 1
अंत में मेल खाने वाली वस्तुओं को काट दें
जबकि प्रारंभ ≤ m_end और प्रारंभ ≤ n_end और X[m_end] = Y[n_end]
m_end := m_end - 1
n_end := n_end - 1
सी = सरणी(प्रारंभ-1..एम_एंड, प्रारंभ-1..एन_एंड)
केवल उन आइटमों पर लूप करें जो बदल गए हैं
मेरे लिए := प्रारंभ..m_end
j के लिए := प्रारंभ..n_end
एल्गोरिदम पहले की तरह जारी है...
सर्वोत्तम स्थिति में, बिना किसी बदलाव वाले अनुक्रम में, यह अनुकूलन सी मैट्रिक्स की आवश्यकता को समाप्त कर देगा। सबसे खराब स्थिति में, अनुक्रम में सबसे पहले और आखिरी आइटम में बदलाव के बाद केवल दो अतिरिक्त तुलनाएं की जाती हैं।
तुलना समय कम करें
अनुभवहीन एल्गोरिथ्म द्वारा लिया गया अधिकांश समय अनुक्रमों में वस्तुओं के बीच तुलना करने में व्यतीत होता है। स्रोत कोड जैसे पाठ्य अनुक्रमों के लिए, आप पंक्तियों को एकल वर्णों के बजाय अनुक्रम तत्वों के रूप में देखना चाहते हैं। इसका मतलब एल्गोरिदम में प्रत्येक चरण के लिए अपेक्षाकृत लंबी स्ट्रिंग की तुलना हो सकता है। दो अनुकूलन किए जा सकते हैं जो इन तुलनाओं में लगने वाले समय को कम करने में मदद कर सकते हैं।
स्ट्रिंग्स को हैश में कम करें
अनुक्रमों में स्ट्रिंग के आकार को कम करने के लिए हैश फंकशन या अंततः, का उपयोग किया जा सकता है। अर्थात्, स्रोत कोड के लिए जहां औसत पंक्ति 60 या अधिक वर्ण लंबी है, उस पंक्ति के लिए हैश या चेकसम केवल 8 से 40 वर्ण लंबा हो सकता है। इसके अतिरिक्त, हैश और चेकसम की यादृच्छिक प्रकृति यह गारंटी देगी कि तुलना तेजी से शॉर्ट-सर्किट होगी, क्योंकि शुरुआत में स्रोत कोड की लाइनें शायद ही कभी बदली जाएंगी।
इस अनुकूलन में तीन प्राथमिक कमियाँ हैं। सबसे पहले, दो अनुक्रमों के लिए हैश की पूर्व-गणना करने के लिए पहले से ही काफी समय खर्च करने की आवश्यकता होती है। दूसरा, नए हैशेड अनुक्रमों के लिए अतिरिक्त मेमोरी आवंटित करने की आवश्यकता है। हालाँकि, यहाँ उपयोग किए गए सरल एल्गोरिदम की तुलना में, ये दोनों कमियाँ अपेक्षाकृत न्यूनतम हैं।
तीसरा दोष हैश टकराव का है। चूंकि चेकसम या हैश के अद्वितीय होने की गारंटी नहीं है, इसलिए इस बात की बहुत कम संभावना है कि दो अलग-अलग आइटमों को एक ही हैश में घटाया जा सकता है। स्रोत कोड में इसकी संभावना नहीं है, लेकिन यह संभव है। इसलिए एक क्रिप्टोग्राफ़िक हैश इस अनुकूलन के लिए कहीं अधिक उपयुक्त होगा, क्योंकि इसकी एन्ट्रॉपी एक साधारण चेकसम की तुलना में काफी अधिक होगी। हालाँकि, लाभ छोटी अनुक्रम लंबाई के लिए क्रिप्टोग्राफ़िक हैश की सेटअप और कम्प्यूटेशनल आवश्यकताओं के लायक नहीं हो सकते हैं।
आवश्यक स्थान कम करें
यदि केवल LCS की लंबाई की आवश्यकता है, तो मैट्रिक्स को कम किया जा सकता है मैट्रिक्स, या करने के लिए एक गतिशील प्रोग्रामिंग दृष्टिकोण के रूप में वेक्टर को मैट्रिक्स के केवल वर्तमान और पिछले कॉलम की आवश्यकता होती है। हिर्शबर्ग का एल्गोरिदम समान द्विघात समय और रैखिक स्थान सीमा में ही इष्टतम अनुक्रम के निर्माण की अनुमति देता है।[8]
कैश छूट को कम करें
चौधरी और रामचंद्रन ने एक द्विघात-समय रैखिक-अंतरिक्ष एल्गोरिदम तैयार किया[9][10] एक इष्टतम अनुक्रम के साथ LCS लंबाई खोजने के लिए जो अपने बेहतर कैश प्रदर्शन के कारण व्यवहार में हिर्शबर्ग के एल्गोरिदम से तेज़ चलता है।[9] कैश-ओब्लिवियस#आदर्शीकृत कैश मॉडल के तहत एल्गोरिदम में एक असम्बद्ध रूप से इष्टतम कैश जटिलता है।[11] दिलचस्प बात यह है कि एल्गोरिथ्म स्वयं कैश-अनभिज्ञ है[11]इसका मतलब यह है कि यह मशीन के कैश पैरामीटर (उदाहरण के लिए, कैश आकार और कैश लाइन आकार) के आधार पर कोई विकल्प नहीं बनाता है।
आगे अनुकूलित एल्गोरिदम
कई एल्गोरिदम मौजूद हैं जो प्रस्तुत गतिशील प्रोग्रामिंग दृष्टिकोण से तेज़ चलते हैं। उनमें से एक हंट-स्ज़िमंस्की एल्गोरिदम है, जो आम तौर पर चलता है के लिए समय ), कहाँ दो अनुक्रमों के बीच मिलान की संख्या है।[12] सीमित वर्णमाला आकार की समस्याओं के लिए, चार रूसी की विधि का उपयोग लॉगरिदमिक कारक द्वारा गतिशील प्रोग्रामिंग एल्गोरिदम के चलने के समय को कम करने के लिए किया जा सकता है।[13]
यादृच्छिक तारों पर व्यवहार
इसके साथ शुरुआत Chvátal & Sankoff (1975),[14] कई शोधकर्ताओं ने सबसे लंबी सामान्य अनुवर्ती लंबाई के व्यवहार की जांच की है जब दो दिए गए तार एक ही वर्णमाला से यादृच्छिक रूप से खींचे जाते हैं। जब वर्णमाला का आकार स्थिर होता है, तो LCS की अपेक्षित लंबाई दो तारों की लंबाई के समानुपाती होती है, और आनुपातिकता के स्थिरांक (वर्णमाला के आकार के आधार पर) च्वाटल-सैंकॉफ स्थिरांक के रूप में जाने जाते हैं। उनके सटीक मूल्य ज्ञात नहीं हैं, लेकिन उनके मूल्यों की ऊपरी और निचली सीमाएं सिद्ध हो चुकी हैं,[15] और यह ज्ञात है कि वे वर्णमाला के आकार के वर्गमूल के विपरीत आनुपातिक रूप से बढ़ते हैं।[16] सबसे लंबी सामान्य अनुवर्ती समस्या के सरलीकृत गणितीय मॉडल को ट्रेसी-विडोम वितरण द्वारा नियंत्रित दिखाया गया है।[17]
यह भी देखें
- सबसे लंबे समय तक बढ़ने वाला क्रम
- सबसे लंबा वैकल्पिक क्रम
- लेवेनशेटिन दूरी
संदर्भ
- ↑ David Maier (1978). "परवर्ती और अतिपरवर्ती पर कुछ समस्याओं की जटिलता". J. ACM. ACM Press. 25 (2): 322–336. doi:10.1145/322063.322075. S2CID 16120634.
- ↑ Wagner, Robert; Fischer, Michael (January 1974). "स्ट्रिंग-टू-स्ट्रिंग सुधार समस्या". Journal of the ACM. 21 (1): 168–173. CiteSeerX 10.1.1.367.5281. doi:10.1145/321796.321811. S2CID 13381535.
- ↑ 3.0 3.1
L. Bergroth and H. Hakonen and T. Raita (2000). "A survey of longest common subsequence algorithms". Proceedings Seventh International Symposium on String Processing and Information Retrieval. SPIRE 2000. pp. 39–48. doi:10.1109/SPIRE.2000.878178. ISBN 0-7695-0746-8. S2CID 10375334.
{{cite book}}:|journal=ignored (help) - ↑ Ronald I. Greenberg (2003-08-06). "सबसे लंबे सामान्य अनुवर्ती की संख्या पर सीमा". arXiv:cs.DM/0301030.
- ↑ Xia, Xuhua (2007). Bioinformatics and the Cell: Modern Computational Approaches in Genomics, Proteomics and Transcriptomics. New York: Springer. p. 24. ISBN 978-0-387-71336-6.
- ↑ Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest and Clifford Stein (2001). "15.4". एल्गोरिदम का परिचय (2nd ed.). MIT Press and McGraw-Hill. pp. 350–355. ISBN 0-262-53196-8.
{{cite book}}: CS1 maint: multiple names: authors list (link) - ↑ Cormen, Thomas H.; Leiserson, Charles E.; Rivest, Ronald L.; Stein, Clifford (2009) [1990]. "Dynamic Programming". Introduction to Algorithms (3rd ed.). MIT Press and McGraw-Hill. p. 394. ISBN 0-262-03384-4.
- ↑ Hirschberg, D. S. (1975). "अधिकतम सामान्य अनुवर्ती की गणना के लिए एक रैखिक अंतरिक्ष एल्गोरिदम". Communications of the ACM. 18 (6): 341–343. doi:10.1145/360825.360861. S2CID 207694727.
- ↑ 9.0 9.1 Chowdhury, Rezaul; Ramachandran, Vijaya (January 2006). "कैश-विस्मृत गतिशील प्रोग्रामिंग". Proceedings of the Seventeenth Annual ACM-SIAM Symposium on Discrete Algorithm (SODA): 591–600. doi:10.1145/1109557.1109622. ISBN 0898716055. S2CID 9650418.
- ↑ Chowdhury, Rezaul; Le, Hai-Son; Ramachandran, Vijaya (July 2010). "जैव सूचना विज्ञान के लिए कैश-विस्मृत गतिशील प्रोग्रामिंग". IEEE/ACM Transactions on Computational Biology and Bioinformatics (TCBB). 7 (3): 495–510. doi:10.1109/TCBB.2008.94. PMID 20671320. S2CID 2532039.
- ↑ 11.0 11.1 Frigo, Matteo; Leiserson, Charles E.; Prokop, Harald; Ramachandran, Sridhar (January 2012). "कैश-विस्मृत एल्गोरिदम". ACM Transactions on Algorithms. 8 (1): 1–22. doi:10.1145/2071379.2071383.
- ↑ Apostolico, Alberto; Galil, Zvi (1997-05-29). पैटर्न मिलान एल्गोरिदम. ISBN 9780195354348.
- ↑ Masek, William J.; Paterson, Michael S. (1980), "A faster algorithm computing string edit distances", Journal of Computer and System Sciences, 20 (1): 18–31, doi:10.1016/0022-0000(80)90002-1, MR 0566639.
- ↑ Chvatal, Václáv; Sankoff, David (1975), "Longest common subsequences of two random sequences", Journal of Applied Probability, 12 (2): 306–315, doi:10.2307/3212444, JSTOR 3212444, MR 0405531, S2CID 250345191.
- ↑ Lueker, George S. (2009), "Improved bounds on the average length of longest common subsequences", Journal of the ACM, 56 (3), A17, doi:10.1145/1516512.1516519, MR 2536132, S2CID 7232681.
- ↑ Kiwi, Marcos; Loebl, Martin; Matoušek, Jiří (2005), "Expected length of the longest common subsequence for large alphabets", Advances in Mathematics, 197 (2): 480–498, arXiv:math/0308234, doi:10.1016/j.aim.2004.10.012, MR 2173842.
- ↑ Majumdar, Satya N.; Nechaev, Sergei (2005), "Exact asymptotic results for the Bernoulli matching model of sequence alignment", Physical Review E, 72 (2): 020901, 4, arXiv:q-bio/0410012, Bibcode:2005PhRvE..72b0901M, doi:10.1103/PhysRevE.72.020901, MR 2177365, PMID 16196539, S2CID 11390762.
बाहरी संबंध
- Dictionary of Algorithms and Data Structures: longest common subsequence
- A collection of implementations of the longest common subsequence in many programming languages
- Find Longest Common Subsequence in Python