दीर्घवर्तिक सामान्य उपानुक्रम (लांगेस्ट कॉमन सब सीक्वेंस): Difference between revisions

From Vigyanwiki
No edit summary
 
(8 intermediate revisions by 4 users not shown)
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|एक उदाहरण फ़ाइल के दो संशोधनों की तुलना, उनके सबसे लंबे सामान्य अनुवर्ती (काले) के आधार पर]]'''सबसे लंबा सामान्य अनुवर्ती (LCS)''' अनुक्रमों के एक सेट (अक्सर केवल दो अनुक्रम) में सभी अनुक्रमों के लिए सामान्य सबसे लंबा अनुवर्ती है। यह सबसे लंबे सामान्य सबस्ट्रिंग से भिन्न है: सबस्ट्रिंग के विपरीत, बाद के अनुक्रमों को मूल अनुक्रमों के भीतर लगातार पदों पर रहने की आवश्यकता नहीं होती है। सबसे लंबे समय तक सामान्य अनुक्रमों की गणना करने की समस्या एक क्लासिक कंप्यूटर विज्ञान समस्या है, जो अंतर उपयोगिता जैसे डेटा तुलना कार्यक्रमों का आधार है, <code>diff</code>और कम्प्यूटेशनल भाषाविज्ञान और जैव सूचना विज्ञान में इसका अनुप्रयोग है। फ़ाइलों के संशोधन-नियंत्रित संग्रह में किए गए कई परिवर्तनों को समेटने के लिए Git जैसी संशोधन नियंत्रण प्रणालियों द्वारा भी इसका व्यापक रूप से उपयोग किया जाता है।
[[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) उनके सबसे लंबे सामान्य अनुवर्ती हैं।


== जटिलता ==
== जटिलता ==
इनपुट अनुक्रमों की यादृच्छिक संख्या के सामान्य मामले के लिए, समस्या [[ एनपी कठिन |एनपी-हार्ड]] है।<ref>{{cite journal| author = David Maier| title = परवर्ती और अतिपरवर्ती पर कुछ समस्याओं की जटिलता| journal = J. ACM| volume = 25| year = 1978| pages = 322&ndash;336| doi = 10.1145/322063.322075| publisher = ACM Press| issue = 2| s2cid = 16120634| doi-access = free}}</ref> जब अनुक्रमों की संख्या स्थिर होती है, तो समस्या को [[गतिशील प्रोग्रामिंग]] द्वारा बहुपद समय में हल किया जा सकता है।
इनपुट अनुक्रमों की यादृच्छिक संख्या के सामान्य स्थिति के लिए, समस्या [[ एनपी कठिन |एनपी-हार्ड]] है।<ref>{{cite journal| author = David Maier| title = परवर्ती और अतिपरवर्ती पर कुछ समस्याओं की जटिलता| journal = J. ACM| volume = 25| year = 1978| pages = 322&ndash;336| doi = 10.1145/322063.322075| publisher = ACM Press| issue = 2| s2cid = 16120634| doi-access = free}}</ref> जब अनुक्रमों की संख्या स्थिर होती है, तो समस्या को [[गतिशील प्रोग्रामिंग]] द्वारा बहुपद समय में हल किया जा सकता है।


दिया गया <math>N</math> लंबाई का क्रम <math>n_1, ..., n_N</math>, एक अनुभवहीन खोज प्रत्येक का परीक्षण करेगी <math>2^{n_1}</math> पहले अनुक्रम के अनुवर्ती यह निर्धारित करने के लिए कि क्या वे शेष अनुक्रमों के भी अनुवर्ती हैं; प्रत्येक अनुवर्ती को शेष अनुक्रमों की लंबाई में रैखिक समय में परीक्षण किया जा सकता है, इसलिए इस एल्गोरिदम के लिए समय होगा
दिया गया <math>N</math> लंबाई का क्रम <math>n_1, ..., n_N</math>, एक अनुभवहीन खोज प्रत्येक का परीक्षण करेगी <math>2^{n_1}</math> पहले अनुक्रम के अनुवर्ती यह निर्धारित करने के लिए कि क्या वे शेष अनुक्रमों के भी अनुवर्ती हैं; प्रत्येक अनुवर्ती को शेष अनुक्रमों की लंबाई में रैखिक समय में परीक्षण किया जा सकता है, इसलिए इस एल्गोरिदम के लिए समय होगा
:<math>O\left( 2^{n_1} \sum_{i>1} n_i\right).</math>
:<math>O\left( 2^{n_1} \sum_{i>1} n_i\right).</math>
''n'' और ''m'' तत्वों के दो अनुक्रमों के मामले में, गतिशील प्रोग्रामिंग दृष्टिकोण का चलने का समय O(''n'' × ''m'') है।<ref>{{cite journal |last1=Wagner |first1=Robert |last2=Fischer |first2=Michael |date=January 1974 |title=स्ट्रिंग-टू-स्ट्रिंग सुधार समस्या|journal=[[Journal of the ACM]] |volume=21 |issue=1 |pages=168–173 |doi=10.1145/321796.321811 |citeseerx=10.1.1.367.5281 |s2cid=13381535 }}</ref> इनपुट अनुक्रमों की एक मनमाने ढंग से संख्या के लिए, गतिशील प्रोग्रामिंग दृष्टिकोण एक समाधान देता है
''n'' और ''m'' एलिमेंटों के दो अनुक्रमों के स्थिति में, गतिशील प्रोग्रामिंग दृष्टिकोण का चलने का समय O(''n'' × ''m'') है।<ref>{{cite journal |last1=Wagner |first1=Robert |last2=Fischer |first2=Michael |date=January 1974 |title=स्ट्रिंग-टू-स्ट्रिंग सुधार समस्या|journal=[[Journal of the ACM]] |volume=21 |issue=1 |pages=168–173 |doi=10.1145/321796.321811 |citeseerx=10.1.1.367.5281 |s2cid=13381535 }}</ref> इनपुट अनुक्रमों की एक मनमाने ढंग से संख्या के लिए, गतिशील प्रोग्रामिंग दृष्टिकोण एक समाधान देता है


:<math>O\left(N \prod_{i=1}^{N} n_i\right).</math>
:<math>O\left(N \prod_{i=1}^{N} n_i\right).</math>
कम जटिलता वाली विधियाँ मौजूद हैं,<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&ndash;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&ndash;48 | doi = 10.1109/SPIRE.2000.878178 | publisher = IEEE Computer Society| s2cid = 10375334 }}</ref>
जो अक्सर LCS की लंबाई, वर्णमाला के आकार या दोनों पर निर्भर करता है।
जो प्रायः LCS की लंबाई, वर्णमाला के आकार या दोनों पर निर्भर करता है।


LCS आवश्यक रूप से अद्वितीय नहीं है; सबसे खराब स्थिति में, इनपुट की लंबाई में सामान्य अनुवर्ती की संख्या घातीय होती है, इसलिए एल्गोरिथम जटिलता कम से कम घातीय होनी चाहिए।<ref>{{cite arXiv | author = Ronald I. Greenberg | title = सबसे लंबे सामान्य अनुवर्ती की संख्या पर सीमा| date = 2003-08-06  | eprint = cs.DM/0301030}}</ref>
LCS आवश्यक रूप से अद्वितीय नहीं है; सबसे खराब स्थिति में, इनपुट की लंबाई में सामान्य अनुवर्ती की संख्या घातीय होती है, इसलिए एल्गोरिथम जटिलता कम से कम घातीय होनी चाहिए।<ref>{{cite arXiv | author = Ronald I. Greenberg | title = सबसे लंबे सामान्य अनुवर्ती की संख्या पर सीमा| date = 2003-08-06  | eprint = cs.DM/0301030}}</ref>
== दो अनुक्रमों के लिए समाधान ==
== दो अनुक्रमों के लिए समाधान ==
LCS समस्या में एक इष्टतम उप-संरचना होती है: समस्या को छोटे, सरल उप-समस्याओं में विभाजित किया जा सकता है, जो बदले में, सरल उप-समस्याओं में विभाजित किया जा सकता है, और इसी तरह, जब तक, अंत में, समाधान तुच्छ नहीं हो जाता। LCS में विशेष रूप से ओवरलैपिंग उपसमस्याएं हैं: उच्च-स्तरीय उप-समस्याओं के समाधान अक्सर निचले स्तर की उप-समस्याओं के समाधान का पुन: उपयोग करते हैं। इन दो गुणों वाली समस्याएं गतिशील प्रोग्रामिंग दृष्टिकोण के लिए उपयुक्त हैं, जिसमें उप-समस्या समाधानों को याद किया जाता है, अर्थात, उप-समस्याओं के समाधान पुन: उपयोग के लिए सेव किये जाते हैं।
LCS समस्या में एक इष्टतम उप-संरचना होती है: समस्या को छोटे, सरल उप-समस्याओं में विभाजित किया जा सकता है, जो बदले में, सरल उप-समस्याओं में विभाजित किया जा सकता है, और इसी तरह, जब तक, अंत में, समाधान तुच्छ नहीं हो जाता। LCS में विशेष रूप से ओवरलैपिंग उपसमस्याएं हैं: उच्च-स्तरीय उप-समस्याओं के समाधान प्रायः निचले स्तर की उप-समस्याओं के समाधान का पुन: उपयोग करते हैं। इन दो गुणों वाली समस्याएं गतिशील प्रोग्रामिंग दृष्टिकोण के लिए उपयुक्त हैं, जिसमें उप-समस्या समाधानों को याद किया जाता है, अर्थात, उप-समस्याओं के समाधान पुन: उपयोग के लिए सेव किये जाते हैं।


=== उपसर्ग ===
=== उपसर्ग ===
Line 54: Line 54:


=== ''LCS'' फ़ंक्शन परिभाषित ===
=== ''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>. अनुक्रमों का यह सेट निम्नलिखित द्वारा दिया गया है।


:<math>
:<math>
Line 103: Line 103:
इस तालिका का उपयोग गणना के प्रत्येक चरण के लिए एलसीएस अनुक्रम को संग्रहीत करने के लिए किया जाता है। दूसरे कॉलम और दूसरी पंक्ति को ε से भर दिया गया है, क्योंकि जब एक रिक्त अनुक्रम की तुलना एक गैर-रिक्त अनुक्रम से की जाती है, तो सबसे लंबा सामान्य अनुवर्ती हमेशा एक रिक्त अनुक्रम होता है।
इस तालिका का उपयोग गणना के प्रत्येक चरण के लिए एलसीएस अनुक्रम को संग्रहीत करने के लिए किया जाता है। दूसरे कॉलम और दूसरी पंक्ति को ε से भर दिया गया है, क्योंकि जब एक रिक्त अनुक्रम की तुलना एक गैर-रिक्त अनुक्रम से की जाती है, तो सबसे लंबा सामान्य अनुवर्ती हमेशा एक रिक्त अनुक्रम होता है।


''LCS''(''R''<sub>1</sub>, ''C''<sub>1</sub>) प्रत्येक अनुक्रम में पहले तत्वों की तुलना करके निर्धारित किया जाता है। G और A समान नहीं हैं, इसलिए यह LCS ("दूसरी संपत्ति का उपयोग करके" दो अनुक्रमों, ''LCS''(''R''<sub>1</sub>, ''C''<sub>0</sub>) और ''LCS''(''R''<sub>0</sub>, ''C''<sub>1</sub>) में से सबसे लंबा प्राप्त करता है। तालिका के अनुसार, ये दोनों रिक्त हैं, इसलिए ''LCS''(''R''<sub>1</sub>, ''C''<sub>1</sub>) भी रिक्त है, जैसा कि नीचे दी गई तालिका में दिखाया गया है। तीर इंगित करते हैं कि अनुक्रम ऊपर की दोनों कोशिकाओं, ''LCS''(''R''<sub>0</sub>, ''C''<sub>1</sub>) और बाईं ओर की कोशिका, ''LCS''(''R''<sub>1</sub>, ''C''<sub>0</sub>) से आता है।
''LCS''(''R''<sub>1</sub>, ''C''<sub>1</sub>) प्रत्येक अनुक्रम में पहले एलिमेंटों की तुलना करके निर्धारित किया जाता है। G और A समान नहीं हैं, इसलिए यह LCS ("दूसरी संपत्ति का उपयोग करके" दो अनुक्रमों, ''LCS''(''R''<sub>1</sub>, ''C''<sub>0</sub>) और ''LCS''(''R''<sub>0</sub>, ''C''<sub>1</sub>) में से सबसे लंबा प्राप्त करता है। तालिका के अनुसार, ये दोनों रिक्त हैं, इसलिए ''LCS''(''R''<sub>1</sub>, ''C''<sub>1</sub>) भी रिक्त है, जैसा कि नीचे दी गई तालिका में दिखाया गया है। तीर इंगित करते हैं कि अनुक्रम ऊपर की दोनों कोशिकाओं, ''LCS''(''R''<sub>0</sub>, ''C''<sub>1</sub>) और बाईं ओर की कोशिका, ''LCS''(''R''<sub>1</sub>, ''C''<sub>0</sub>) से आता है।


''LCS''(''R''<sub>1</sub>, ''C''<sub>2</sub>) का निर्धारण G और G की तुलना करके किया जाता है। वे मेल खाते हैं, इसलिए G को ऊपरी बाएँ क्रम में जोड़ा जाता है, ''LCS''(''R''<sub>0</sub>, ''C''<sub>1</sub>), जो (ε) है, दे रहा है (εG), जो कि (G) है .
''LCS''(''R''<sub>1</sub>, ''C''<sub>2</sub>) का निर्धारण G और G की तुलना करके किया जाता है। वे मेल खाते हैं, इसलिए G को ऊपरी बाएँ क्रम में जोड़ा जाता है, ''LCS''(''R''<sub>0</sub>, ''C''<sub>1</sub>), जो (ε) है, दे रहा है (εG), जो कि (G) है .
Line 146: Line 146:
|-
|-
|}
|}
''LCS''(''R''<sub>2</sub>, ''C''<sub>1</sub>) के लिए, A की तुलना A से की जाती है। दोनों तत्व मेल खाते हैं, इसलिए A को ε में जोड़ा जाता है, जिससे (A) मिलता है।
''LCS''(''R''<sub>2</sub>, ''C''<sub>1</sub>) के लिए, A की तुलना A से की जाती है। दोनों एलिमेंट मेल खाते हैं, इसलिए A को ε में जोड़ा जाता है, जिससे (A) मिलता है।


''LCS''(''R''<sub>2</sub>, ''C''<sub>2</sub>) के लिए, A और G मेल नहीं खाते हैं, इसलिए ''LCS''(''R''<sub>1</sub>, ''C''<sub>2</sub>) में से सबसे लंबा, जो कि (G) है, और ''LCS''(''R''<sub>2</sub>, ''C''<sub>1</sub>), जो कि (A) है, का उपयोग किया जाता है। इस मामले में, उनमें से प्रत्येक में एक तत्व होता है, इसलिए इस एलसीएस को दो अनुवर्ती दिए गए हैं: (A) और (G)।
''LCS''(''R''<sub>2</sub>, ''C''<sub>2</sub>) के लिए, A और G मेल नहीं खाते हैं, इसलिए ''LCS''(''R''<sub>1</sub>, ''C''<sub>2</sub>) में से सबसे लंबा, जो कि (G) है, और ''LCS''(''R''<sub>2</sub>, ''C''<sub>1</sub>), जो कि (A) है, का उपयोग किया जाता है। इस स्थिति में, उनमें से प्रत्येक में एक एलिमेंट होता है, इसलिए इस एलसीएस को दो अनुवर्ती दिए गए हैं: (A) और (G)।


''LCS''(''R''<sub>2</sub>, ''C''<sub>3</sub>) के लिए, A, C से मेल नहीं खाता है। ''LCS''(''R''<sub>2</sub>, ''C''<sub>2</sub>) में अनुक्रम (A) और (G) शामिल हैं; LCS(''R''<sub>1</sub>, ''C''<sub>3</sub>) (G) है, जो पहले से ही ''LCS''(''R''<sub>2</sub>, ''C''<sub>2</sub>) में समाहित है। परिणाम यह है कि ''LCS''(''R''<sub>2</sub>, ''C''<sub>3</sub>) में दो अनुवर्ती, (A) और (G) भी शामिल हैं।
''LCS''(''R''<sub>2</sub>, ''C''<sub>3</sub>) के लिए, A, C से मेल नहीं खाता है। ''LCS''(''R''<sub>2</sub>, ''C''<sub>2</sub>) में अनुक्रम (A) और (G) सम्मिलित हैं; LCS(''R''<sub>1</sub>, ''C''<sub>3</sub>) (G) है, जो पहले से ही ''LCS''(''R''<sub>2</sub>, ''C''<sub>2</sub>) में समाहित है। परिणाम यह है कि ''LCS''(''R''<sub>2</sub>, ''C''<sub>3</sub>) में दो अनुवर्ती, (A) और (G) भी सम्मिलित हैं।


''LCS''(''R''<sub>2</sub>, ''C''<sub>4</sub>) के लिए, A, A से मेल खाता है, जो कि (GA) देते हुए ऊपरी बाएँ सेल से जुड़ा हुआ है।
''LCS''(''R''<sub>2</sub>, ''C''<sub>4</sub>) के लिए, A, A से मेल खाता है, जो कि (GA) देते हुए ऊपरी बाएँ सेल से जुड़ा हुआ है।
Line 190: Line 190:
''LCS''(''R''<sub>3</sub>, ''C''<sub>1</sub>) के लिए, C और A मेल नहीं खाते हैं, इसलिए ''LCS''(''R''<sub>3</sub>, ''C''<sub>1</sub>) को दो अनुक्रमों में से सबसे लंबा अनुक्रम मिलता है, (A)।
''LCS''(''R''<sub>3</sub>, ''C''<sub>1</sub>) के लिए, C और A मेल नहीं खाते हैं, इसलिए ''LCS''(''R''<sub>3</sub>, ''C''<sub>1</sub>) को दो अनुक्रमों में से सबसे लंबा अनुक्रम मिलता है, (A)।


''LCS''(''R''<sub>3</sub>, ''C''<sub>2</sub>) के लिए, C और G मेल नहीं खाते। ''LCS''(''R''<sub>3</sub>, ''C''<sub>1</sub>) और ''LCS''(''R''<sub>2</sub>, ''C''<sub>2</sub>) दोनों में एक तत्व है। परिणाम यह है कि ''LCS''(''R''<sub>3</sub>, ''C''<sub>2</sub>) में दो अनुवर्ती, (A) और (G) शामिल हैं।
''LCS''(''R''<sub>3</sub>, ''C''<sub>2</sub>) के लिए, C और G मेल नहीं खाते। ''LCS''(''R''<sub>3</sub>, ''C''<sub>1</sub>) और ''LCS''(''R''<sub>2</sub>, ''C''<sub>2</sub>) दोनों में एक एलिमेंट है। परिणाम यह है कि ''LCS''(''R''<sub>3</sub>, ''C''<sub>2</sub>) में दो अनुवर्ती, (A) और (G) सम्मिलित हैं।


''LCS''(''R''<sub>3</sub>, ''C''<sub>3</sub>) के लिए, C और C मेल खाते हैं, इसलिए C को ''LCS''(''R''<sub>2</sub>, ''C''<sub>2</sub>) में जोड़ा जाता है, जिसमें दो अनुवर्ती (A) और (G) होते हैं, जो (AC) और (GC) देते हैं।
''LCS''(''R''<sub>3</sub>, ''C''<sub>3</sub>) के लिए, C और C मेल खाते हैं, इसलिए C को ''LCS''(''R''<sub>2</sub>, ''C''<sub>2</sub>) में जोड़ा जाता है, जिसमें दो अनुवर्ती (A) और (G) होते हैं, जो (AC) और (GC) देते हैं।


''LCS''(''R''<sub>3</sub>, ''C''<sub>4</sub>) के लिए, C और A मेल नहीं खाते। ''LCS''(''R''<sub>3</sub>, ''C''<sub>3</sub>)), जिसमें (AC) और (GC), और ''LCS''(''R''<sub>2</sub>, ''C''<sub>4</sub>), जिसमें (GA) शामिल है, को मिलाने पर कुल तीन अनुक्रम मिलते हैं: (AC), (GC), और (GA) ).
''LCS''(''R''<sub>3</sub>, ''C''<sub>4</sub>) के लिए, C और A मेल नहीं खाते। ''LCS''(''R''<sub>3</sub>, ''C''<sub>3</sub>)), जिसमें (AC) और (GC), और ''LCS''(''R''<sub>2</sub>, ''C''<sub>4</sub>), जिसमें (GA) सम्मिलित है, को मिलाने पर कुल तीन अनुक्रम मिलते हैं: (AC), (GC), और (GA) ).


अंततः, ''LCS''(''R''<sub>3</sub>, ''C''<sub>5</sub>) के लिए, C और T मेल नहीं खाते। परिणाम यह है कि ''LCS''(''R''<sub>3</sub>, ''C''<sub>5</sub>) में तीन अनुक्रम, (AC), (GC), और (GA) भी शामिल हैं।
अंततः, ''LCS''(''R''<sub>3</sub>, ''C''<sub>5</sub>) के लिए, C और T मेल नहीं खाते। परिणाम यह है कि ''LCS''(''R''<sub>3</sub>, ''C''<sub>5</sub>) में तीन अनुक्रम, (AC), (GC), और (GA) भी सम्मिलित हैं।
{| class="wikitable" style="text-align:center"
{| class="wikitable" style="text-align:center"
|+ पूर्ण LCS तालिका
|+ पूर्ण LCS तालिका
Line 230: Line 230:
|-
|-
|}
|}
अंतिम परिणाम यह है कि अंतिम सेल में (AGCAT) और (GAC) के सभी सबसे लंबे अनुवर्ती सामान्य शामिल हैं; ये (AC), (GC), और (GA) हैं। तालिका उपसर्गों की प्रत्येक संभावित जोड़ी के लिए सबसे लंबे सामान्य अनुवर्ती को भी दर्शाती है। उदाहरण के लिए, (AGC) और (GA) के लिए, सबसे लंबे सामान्य अनुवर्ती (A) और (G) हैं।
अंतिम परिणाम यह है कि अंतिम सेल में (AGCAT) और (GAC) के सभी सबसे लंबे अनुवर्ती सामान्य सम्मिलित हैं; ये (AC), (GC), और (GA) हैं। तालिका उपसर्गों की प्रत्येक संभावित जोड़ी के लिए सबसे लंबे सामान्य अनुवर्ती को भी दर्शाती है। उदाहरण के लिए, (AGC) और (GA) के लिए, सबसे लंबे सामान्य अनुवर्ती (A) और (G) हैं।


=== ट्रेसबैक दृष्टिकोण ===
=== ट्रेसबैक दृष्टिकोण ===
LCS तालिका की एक पंक्ति की LCS की गणना के लिए केवल वर्तमान पंक्ति और पिछली पंक्ति के समाधान की आवश्यकता होती है। फिर भी, लंबे अनुक्रमों के लिए, ये अनुक्रम असंख्य और लंबे हो सकते हैं, जिसके लिए बहुत अधिक भंडारण स्थान की आवश्यकता होती है। वास्तविक अनुवर्ती को नहीं, बल्कि अनुवर्ती की लंबाई और तीरों की दिशा को सेव कर स्टोरेज स्पेस को बचाया जा सकता है, जैसा कि नीचे दी गई तालिका में है।
LCS तालिका की एक पंक्ति की LCS की गणना के लिए केवल वर्तमान पंक्ति और पिछली पंक्ति के समाधान की आवश्यकता होती है। फिर भी, लंबे अनुक्रमों के लिए, ये अनुक्रम असंख्य और लंबे हो सकते हैं, जिसके लिए बहुत अधिक भंडारण स्पेस की आवश्यकता होती है। वास्तविक अनुवर्ती को नहीं, बल्कि अनुवर्ती की लंबाई और तीरों की दिशा को सेव कर स्टोरेज स्पेस को बचाया जा सकता है, जैसा कि नीचे दी गई तालिका में है।


{| class="wikitable" style="text-align:center"
{| class="wikitable" style="text-align:center"
|+ अनुक्रमों के स्थान पर लंबाई संग्रहित करना
|+ अनुक्रमों के स्पेस पर लंबाई संग्रहित करना
|-
|-
!  || ε || A || G || C || A || T
!  || ε || A || G || C || A || T
Line 268: Line 268:
|-
|-
|}
|}
वास्तविक अनुवर्ती एक "ट्रेसबैक" प्रक्रिया में निकाले जाते हैं जो तालिका में अंतिम सेल से शुरू होकर पीछे की ओर तीरों का अनुसरण करता है। जब लंबाई कम हो जाती है, तो अनुक्रमों में एक सामान्य तत्व होना चाहिए। जब किसी कक्ष में दो तीर दिखाए जाते हैं तो कई पथ संभव होते हैं। इस तरह के विश्लेषण के लिए नीचे तालिका दी गई है, जिसमें उन कोशिकाओं में रंगीन संख्याएँ हैं जहाँ लंबाई घटने वाली है। बोल्ड नंबर अनुक्रम (GA) का पता लगाते हैं।<ref>{{cite book | author = [[Thomas H. Cormen]], [[Charles E. Leiserson]], [[Ronald L. Rivest]] and [[Clifford Stein]] | title = एल्गोरिदम का परिचय| publisher = MIT Press and McGraw-Hill | year = 2001 | isbn = 0-262-53196-8 | edition = 2nd | chapter = 15.4 | pages = 350–355 | title-link = एल्गोरिदम का परिचय}}</ref>
वास्तविक अनुवर्ती एक "ट्रेसबैक" प्रक्रिया में निकाले जाते हैं जो तालिका में अंतिम सेल से शुरू होकर पीछे की ओर तीरों का अनुसरण करता है। जब लंबाई कम हो जाती है, तो अनुक्रमों में एक सामान्य एलिमेंट होना चाहिए। जब किसी कक्ष में दो तीर दिखाए जाते हैं तो कई पथ संभव होते हैं। इस तरह के विश्लेषण के लिए नीचे तालिका दी गई है, जिसमें उन कोशिकाओं में रंगीन संख्याएँ हैं जहाँ लंबाई घटने वाली है। बोल्ड नंबर अनुक्रम (GA) का पता लगाते हैं।<ref>{{cite book | author = [[Thomas H. Cormen]], [[Charles E. Leiserson]], [[Ronald L. Rivest]] and [[Clifford Stein]] | title = एल्गोरिदम का परिचय| publisher = MIT Press and McGraw-Hill | year = 2001 | isbn = 0-262-53196-8 | edition = 2nd | chapter = 15.4 | pages = 350–355 | title-link = एल्गोरिदम का परिचय}}</ref>


{| class="wikitable" style="text-align:center"
{| class="wikitable" style="text-align:center"
Line 310: Line 310:


:<math>d'(X,Y) = n + m - 2 \cdot \left|LCS(X,Y)\right|.</math>
:<math>d'(X,Y) = n + m - 2 \cdot \left|LCS(X,Y)\right|.</math>
== गतिशील प्रोग्रामिंग समाधान के लिए कोड ==
== डायनामिक प्रोग्रामिंग समाधान के लिए कोड ==
=== LCS की लंबाई की गणना ===
=== LCS की लंबाई की गणना ===
नीचे दिया गया फ़ंक्शन इनपुट अनुक्रम के रूप में लेता है <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>
नीचे दिया गया फ़ंक्शन इनपुट अनुक्रम के रूप में लेता है <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])
    '''function''' 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,जे])
    वापसी सी[एम,एन]
 
वैकल्पिक रूप से, संस्मरण का उपयोग किया जा सकता है।
 
====सी#==== में उदाहरण
<syntaxhighlight lang="csharp">
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];
}
</syntaxhighlight>
 


    C = array(0..m, 0..n)
    '''for''' i := 0..m
        C[i,0] = 0
    '''for''' j := 0..n
        C[0,j] = 0
    '''for''' i := 1..m
        '''for''' j := 1..n
            '''if''' X[i] = Y[j]
                C[i,j] := C[i-1,j-1] + 1
            '''else'''
                C[i,j] := max(C[i,j-1], C[i-1,j])
    '''return''' C[m,n]
वैकल्पिक रूप से, मेमोइज़ेशन का उपयोग किया जा सकता है।
=== LCS पढ़ना ===
=== LCS पढ़ना ===
निम्नलिखित फ़ंक्शन गणना करते समय लिए गए विकल्पों को [[बैक ट्रैकिंग]] करता है <code>C</code> मेज़। यदि उपसर्गों में अंतिम वर्ण समान हैं, तो उन्हें LCS में होना चाहिए। यदि नहीं, तो जांचें कि किस चीज़ ने रखने का सबसे बड़ा LCS दिया <math>x_i</math> और <math>y_j</math>, और वही चुनाव करें। यदि वे समान रूप से लंबे हों तो बस एक चुनें। फ़ंक्शन को कॉल करें <code>i=m</code> और <code>j=n</code>.
निम्नलिखित फ़ंक्शन गणना करते समय लिए गए विकल्पों को [[बैक ट्रैकिंग]] करता है <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)
  '''function''' backtrack(C[0..m,0..n], X[1..m], Y[1..n], i, j)
     यदि मैं = 0 या जे = 0
     '''if''' i = 0 or j = 0
         वापस करना
         '''return''' ""
     यदि X[i] = Y[j]
     '''if'''  X[i] = Y[j]
         बैकट्रैक लौटें (सी, एक्स, वाई, आई-1, जे-1) + एक्स[आई]
         '''return''' backtrack(C, X, Y, i-1, j-1) + X[i]
     यदि C[i,j-1] > C[i-1,j]
     '''if''' C[i,j-1] > C[i-1,j]
         बैकट्रैक लौटें (सी, एक्स, वाई, आई, जे-1)
         '''return''' backtrack(C, X, Y, i, j-1)
    बैकट्रैक लौटें (सी, एक्स, वाई, आई-1, जे)
    '''return''' backtrack(C, X, Y, i-1, j)
 
====सी#==== में उदाहरण
<syntaxhighlight lang="csharp">
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);
}
</syntaxhighlight>
 
 
=== सभी LCS को पढ़ना ===
=== सभी LCS को पढ़ना ===
अगर चुन रहे हैं <math>x_i</math> और <math>y_j</math> समान रूप से लंबा परिणाम देगा, दोनों परिणामी अनुवर्ती पढ़ें। इसे इस फ़ंक्शन द्वारा एक सेट के रूप में लौटाया जाता है। ध्यान दें कि यह फ़ंक्शन बहुपद नहीं है, क्योंकि यदि तार समान हैं तो यह लगभग हर चरण में शाखाबद्ध हो सकता है।
अगर चुन रहे हैं <math>x_i</math> और <math>y_j</math> समान रूप से लंबा परिणाम देगा, दोनों परिणामी अनुवर्ती पढ़ें। इसे इस फ़ंक्शन द्वारा एक सेट के रूप में लौटाया जाता है। ध्यान दें कि यह फ़ंक्शन बहुपद नहीं है, क्योंकि यदि तार समान हैं तो यह लगभग हर चरण में शाखाबद्ध हो सकता है।


  फ़ंक्शन बैकट्रैकऑल(C[0..m,0..n], X[1..m], Y[1..n], i, j)
  '''function''' backtrackAll(C[0..m,0..n], X[1..m], Y[1..n], i, j)
     यदि मैं = 0 या जे = 0
     if i = 0 or j = 0
         वापस करना { }
         '''return''' {""}
     यदि X[i] = Y[j]
     '''if''' X[i] = Y[j]
         बैकट्रैकऑल में सभी Z के लिए {Z + X[i] लौटाएं(C, X, Y, i-1, j-1)}
         '''return''' {Z + X[i] '''for all''' Z '''in''' backtrackAll(C, X, Y, i-1, j-1)}
     आर := {}
     R := {}
     यदि C[i,j-1] ≥ C[i-1,j]
     '''if''' C[i,j-1] ≥ C[i-1,j]
         आर := बैकट्रैकऑल(सी, एक्स, वाई, आई, जे-1)
         R := backtrackAll(C, X, Y, i, j-1)
     यदि C[i-1,j] ≥ C[i,j-1]
     '''if''' C[i-1,j] ≥ C[i,j-1]
         आर := आर बैकट्रैकऑल(सी, एक्स, वाई, आई-1, जे)
         R := R backtrackAll(C, X, Y, i-1, j)
     वापसी आर
     '''return''' R


=== [[अंतर]] प्रिंट करें ===
=== [[अंतर|diff]] प्रिंट करें ===
यह फ़ंक्शन सी मैट्रिक्स के माध्यम से बैकट्रैक करेगा, और दो अनुक्रमों के बीच अंतर को प्रिंट करेगा। ध्यान दें कि यदि आप आदान-प्रदान करते हैं तो आपको एक अलग उत्तर मिलेगा <code>≥</code> और <code>&lt;</code>, साथ <code>&gt;</code> और <code>≤</code> नीचे।
यह फ़ंक्शन C मैट्रिक्स के माध्यम से बैकट्रैक करेगा, और दो अनुक्रमों के बीच अंतर प्रिंट करेगा। ध्यान दें कि यदि आप <code>≥</code> और<code>&lt;</code> को नीचे <code>&gt;</code> और <code>≤</code>से बदलते हैं तो आपको एक अलग उत्तर मिलेगा।


  फ़ंक्शन printDiff(C[0..m,0..n], X[1..m], Y[1..n], i, j)
  '''function''' printDiff(C[0..m,0..n], X[1..m], Y[1..n], i, j)
     यदि i >= 0 और j >= 0 और X[i] = Y[j]
     '''if''' i >= 0 '''and''' j >= 0 '''and''' X[i] = Y[j]
         प्रिंटडिफ (सी, एक्स, वाई, आई-1, जे-1)
         printDiff(C, X, Y, i-1, j-1)
         प्रिंट + एक्स[i]
         print "  " + X[i]
     अन्यथा यदि j > 0 और (i = 0 या C[i,j-1] ≥ C[i-1,j])
     '''else if''' j > 0 '''and''' (i = 0 '''or''' C[i,j-1] ≥ C[i-1,j])
         प्रिंटडिफ (सी, एक्स, वाई, आई, जे-1)
         printDiff(C, X, Y, i, j-1)
         प्रिंट + + वाई[जे]
         print "+ " + Y[j]
     अन्यथा यदि i > 0 और (j = 0 या C[i,j-1] < C[i-1,j])
     '''else if''' i > 0 '''and''' (j = 0 '''or''' C[i,j-1] < C[i-1,j])
         प्रिंटडिफ (सी, एक्स, वाई, आई-1, जे)
         printDiff(C, X, Y, i-1, j)
         प्रिंट - + एक्स[i]
         print "- " + X[i]
     अन्य
     '''else'''
         छपाई
         print ""


=== उदाहरण ===
=== उदाहरण ===
होने देना <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>.
मान लीजिये <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 445: Line 404:
| 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> 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>.
<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>.के बीच में लेने से मेल खाता है।


== कोड अनुकूलन ==
== कोड अनुकूलन ==
वास्तविक दुनिया के मामलों के लिए इसे तेज़ करने के लिए उपरोक्त एल्गोरिदम में कई अनुकूलन किए जा सकते हैं।
वास्तविक दुनिया के मामलों के लिए इसे गति देने के लिए उपरोक्त एल्गोरिदम में कई अनुकूलन किए जा सकते हैं।


=== समस्या सेट कम करें ===
=== समस्या सेट कम करें ===
अनुभवहीन एल्गोरिथ्म में सी मैट्रिक्स अनुक्रमों की लंबाई के साथ [[द्विघात वृद्धि]]। दो 100-आइटम अनुक्रमों के लिए, 10,000-आइटम मैट्रिक्स की आवश्यकता होगी, और 10,000 तुलनाएँ करने की आवश्यकता होगी। अधिकांश वास्तविक दुनिया के मामलों में, विशेष रूप से स्रोत कोड अंतर और पैच में, फ़ाइलों की शुरुआत और अंत शायद ही कभी बदलते हैं, और लगभग निश्चित रूप से एक ही समय में दोनों नहीं। यदि अनुक्रम के बीच में केवल कुछ आइटम बदले गए हैं, तो शुरुआत और अंत को हटाया जा सकता है। इससे न केवल मैट्रिक्स के लिए मेमोरी आवश्यकताएं कम हो जाती हैं, बल्कि तुलनाओं की संख्या भी कम हो जाती है।
अनुभवहीन एल्गोरिथ्म में सी मैट्रिक्स अनुक्रमों की लंबाई के साथ चतुर्भुज रूप से बढ़ता है। दो 100-आइटम अनुक्रमों के लिए, 10,000-आइटम मैट्रिक्स की आवश्यकता होगी, और 10,000 तुलनाएं करने की आवश्यकता होगी। वास्तविक दुनिया के अधिकांश मामलों में, विशेष रूप से स्रोत कोड अंतर और पैच में, फ़ाइलों की प्रारम्भ और अंत शायद ही कभी बदलते हैं, और लगभग निश्चित रूप से एक ही समय में दोनों नहीं। यदि अनुक्रम के मध्य में केवल कुछ आइटम बदले गए हैं, तो प्रारम्भ और अंत को हटाया जा सकता है। यह न केवल मैट्रिक्स के लिए मेमोरी आवश्यकताओं को कम करता है, बल्कि की जाने वाली तुलनाओं की संख्या को भी कम करता है।


  फ़ंक्शन LCS(X[1..m], Y[1..n])
  function LCS(X[1..m], Y[1..n])
     प्रारंभ := 1
     start := 1
     m_end := m
     m_end := m
     n_end := n
     n_end := n
     ''शुरुआत में मेल खाने वाली वस्तुओं को काट दें''
     ''trim off the matching items at the beginning''
     जबकि प्रारंभ ≤ m_end और प्रारंभ ≤ n_end और X[प्रारंभ] = Y[प्रारंभ]
     '''while''' start ≤ m_end '''and''' start ≤ n_end '''and''' X[start] = Y[start]
         प्रारंभ := प्रारंभ + 1
         start := start + 1
     ''अंत में मेल खाने वाली वस्तुओं को काट दें''
     ''trim off the matching items at the end''
     जबकि प्रारंभ ≤ m_end और प्रारंभ ≤ n_end और X[m_end] = Y[n_end]
     '''while''' start ≤ m_end '''and''' start ≤ n_end '''and''' X[m_end] = Y[n_end]
         m_end := m_end - 1
         m_end := m_end - 1
         n_end := n_end - 1
         n_end := n_end - 1
     सी = सरणी(प्रारंभ-1..एम_एंड, प्रारंभ-1..एन_एंड)
     C = array(start-1..m_end, start-1..n_end)
     ''केवल उन आइटमों पर लूप करें जो बदल गए हैं''
     ''only loop over the items that have changed''
     मेरे लिए := प्रारंभ..m_end
     '''for''' i := start..m_end
         j के लिए := प्रारंभ..n_end
         '''for''' j := start..n_end
             ''एल्गोरिदम पहले की तरह जारी है...''
             the algorithm continues as before ...


सर्वोत्तम स्थिति में, बिना किसी बदलाव वाले अनुक्रम में, यह अनुकूलन सी मैट्रिक्स की आवश्यकता को समाप्त कर देगा। सबसे खराब स्थिति में, अनुक्रम में सबसे पहले और आखिरी आइटम में बदलाव के बाद केवल दो अतिरिक्त तुलनाएं की जाती हैं।
सर्वोत्तम स्थिति में, बिना किसी बदलाव वाले अनुक्रम में, यह अनुकूलन सी मैट्रिक्स की आवश्यकता को समाप्त कर देगा। सबसे खराब स्थिति में, अनुक्रम में सबसे पहले और आखिरी आइटम में बदलाव के बाद केवल दो अतिरिक्त तुलनाएं की जाती हैं।


=== तुलना समय कम करें ===
=== तुलना समय कम करें ===
अनुभवहीन एल्गोरिथ्म द्वारा लिया गया अधिकांश समय अनुक्रमों में वस्तुओं के बीच तुलना करने में व्यतीत होता है। स्रोत कोड जैसे पाठ्य अनुक्रमों के लिए, आप पंक्तियों को एकल वर्णों के बजाय अनुक्रम तत्वों के रूप में देखना चाहते हैं। इसका मतलब एल्गोरिदम में प्रत्येक चरण के लिए अपेक्षाकृत लंबी स्ट्रिंग की तुलना हो सकता है। दो अनुकूलन किए जा सकते हैं जो इन तुलनाओं में लगने वाले समय को कम करने में मदद कर सकते हैं।
अनुभवहीन एल्गोरिथ्म द्वारा लिया गया अधिकांश समय अनुक्रमों में वस्तुओं के बीच तुलना करने में खर्च होता है। स्रोत कोड जैसे पाठ अनुक्रमों के लिए, आप एकल वर्णों के बजाय पंक्तियों को अनुक्रम एलिमेंटों के रूप में देखना चाहते हैं। इसका अर्थ एल्गोरिदम में प्रत्येक चरण के लिए अपेक्षाकृत लंबी स्ट्रिंग की तुलना हो सकता है। दो अनुकूलन किए जा सकते हैं जो इन तुलनाओं में लगने वाले समय को कम करने में सहायता कर सकते हैं।


=== स्ट्रिंग्स को हैश में कम करें ===
=== स्ट्रिंग्स को हैश में कम करें ===
अनुक्रमों में स्ट्रिंग के आकार को कम करने के लिए [[हैश फंकशन]] या [[ अंततः, ]] का उपयोग किया जा सकता है। अर्थात्, स्रोत कोड के लिए जहां औसत पंक्ति 60 या अधिक वर्ण लंबी है, उस पंक्ति के लिए हैश या चेकसम केवल 8 से 40 वर्ण लंबा हो सकता है। इसके अतिरिक्त, हैश और चेकसम की यादृच्छिक प्रकृति यह गारंटी देगी कि तुलना तेजी से शॉर्ट-सर्किट होगी, क्योंकि शुरुआत में स्रोत कोड की लाइनें शायद ही कभी बदली जाएंगी।
अनुक्रमों में स्ट्रिंग के आकार को कम करने के लिए [[हैश फंकशन]] या चेकसम का उपयोग किया जा सकता है। अर्थात्, स्रोत कोड के लिए जहां औसत पंक्ति 60 या अधिक वर्ण लंबी है, उस पंक्ति के लिए हैश या चेकसम केवल 8 से 40 वर्ण लंबा हो सकता है। इसके अतिरिक्त, हैश और चेकसम की यादृच्छिक प्रकृति यह गारंटी देगी कि तुलना तेजी से शॉर्ट-सर्किट होगी, क्योंकि स्रोत कोड की लाइनें प्रारम्भ में शायद ही कभी बदली जाएंगी।
 
इस अनुकूलन में तीन प्राथमिक कमियाँ हैं। सबसे पहले, दो अनुक्रमों के लिए हैश की पूर्व-गणना करने के लिए पहले से ही काफी समय खर्च करने की आवश्यकता होती है। दूसरा, नए हैशेड अनुक्रमों के लिए अतिरिक्त मेमोरी आवंटित करने की आवश्यकता है। हालाँकि, यहाँ उपयोग किए गए सरल एल्गोरिदम की तुलना में, ये दोनों कमियाँ अपेक्षाकृत न्यूनतम हैं।
 
तीसरा दोष हैश टकराव का है। चूंकि चेकसम या हैश के अद्वितीय होने की गारंटी नहीं है, इसलिए इस बात की बहुत कम संभावना है कि दो अलग-अलग आइटमों को एक ही हैश में घटाया जा सकता है। स्रोत कोड में इसकी संभावना नहीं है, लेकिन यह संभव है। इसलिए एक क्रिप्टोग्राफ़िक हैश इस अनुकूलन के लिए कहीं अधिक उपयुक्त होगा, क्योंकि इसकी एन्ट्रॉपी एक साधारण चेकसम की तुलना में काफी अधिक होगी। हालाँकि, लाभ छोटी अनुक्रम लंबाई के लिए क्रिप्टोग्राफ़िक हैश की सेटअप और कम्प्यूटेशनल आवश्यकताओं के लायक नहीं हो सकते हैं।


=== आवश्यक स्थान कम करें ===
इस अनुकूलन में तीन प्राथमिक कमियाँ हैं। सबसे पहले, दो अनुक्रमों के लिए हैश की पूर्व-गणना करने के लिए पहले से ही काफी समय खर्च करने की आवश्यकता है। दूसरा, नए हैशेड अनुक्रमों के लिए अतिरिक्त मेमोरी आवंटित करने की आवश्यकता है। हालाँकि, यहां उपयोग किए गए अनुभवहीन एल्गोरिदम की तुलना में, ये दोनों कमियां अपेक्षाकृत न्यूनतम हैं।
यदि केवल 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> एक इष्टतम अनुक्रम के साथ 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" />इसका मतलब यह है कि यह मशीन के कैश पैरामीटर (उदाहरण के लिए, कैश आकार और कैश लाइन आकार) के आधार पर कोई विकल्प नहीं बनाता है।
यदि केवल ''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> एक इष्टतम अनुक्रम के साथ ''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" /> इसका मतलब यह है कि यह मशीन के कैश पैरामीटर (उदाहरण के लिए, कैश आकार और कैश लाइन आकार) के आधार पर कोई विकल्प नहीं बनाता है।


=== आगे अनुकूलित एल्गोरिदम ===
=== आगे अनुकूलित एल्गोरिदम ===
कई एल्गोरिदम मौजूद हैं जो प्रस्तुत गतिशील प्रोग्रामिंग दृष्टिकोण से तेज़ चलते हैं। उनमें से एक हंट-स्ज़िमंस्की एल्गोरिदम है, जो आम तौर पर चलता है <math>O((n + r)\log(n))</math> के लिए समय <math>n > m</math>), कहाँ <math>r</math> दो अनुक्रमों के बीच मिलान की संख्या है।<ref>{{Cite book | url=https://books.google.com/books?id=mFd_grFyiT4C&q=hunt+szymanski+algorithm&pg=PA132 |title = पैटर्न मिलान एल्गोरिदम|isbn = 9780195354348|last1 = Apostolico|first1 = Alberto|last2 = Galil|first2 = Zvi|date = 1997-05-29}}</ref> सीमित वर्णमाला आकार की समस्याओं के लिए, चार रूसी की विधि का उपयोग लॉगरिदमिक कारक द्वारा गतिशील प्रोग्रामिंग एल्गोरिदम के चलने के समय को कम करने के लिए किया जा सकता है।<ref>{{citation
कई एल्गोरिदम उपस्थित हैं जो प्रस्तुत गतिशील प्रोग्रामिंग दृष्टिकोण की तुलना में तेज़ चलते हैं। उनमें से एक हंट-ज़िमांस्की एल्गोरिदम है, जो सामान्यतः <math>O((n + r)\log(n))</math> समय <math>n > m</math> (के लिए) में चलता है, जहां <math>r</math> दो अनुक्रमों के बीच मिलान की संख्या है।<ref>{{Cite book | url=https://books.google.com/books?id=mFd_grFyiT4C&q=hunt+szymanski+algorithm&pg=PA132 |title = पैटर्न मिलान एल्गोरिदम|isbn = 9780195354348|last1 = Apostolico|first1 = Alberto|last2 = Galil|first2 = Zvi|date = 1997-05-29}}</ref> गठबंधन हुई वर्णमाला के आकार की समस्याओं के लिए, लॉगरिदमिक कारक द्वारा गतिशील प्रोग्रामिंग एल्गोरिदम के चलने के समय को कम करने के लिए चार रूसी की विधि का उपयोग किया जा सकता है।<ref>{{citation
  | last1 = Masek | first1 = William J.
  | last1 = Masek | first1 = William J.
  | last2 = Paterson | first2 = Michael S. | author2-link = Mike Paterson
  | last2 = Paterson | first2 = Michael S. | author2-link = Mike Paterson
Line 502: Line 459:
  | year = 1980| doi-access = free
  | year = 1980| doi-access = free
  }}.</ref>
  }}.</ref>
== यादृच्छिक स्ट्रिंग्स पर व्यवहार ==
{{main|च्वाटल-सैंकॉफ़ स्थिरांक}}


 
च्वाटल और सैंकोफ़ (1975) से प्रारम्भ करते हुए,<ref>{{citation
== यादृच्छिक स्ट्रिंग्स पर व्यवहार ==
{{main|Chvátal–Sankoff constants}}
इसके साथ शुरुआत {{harvtxt|Chvátal|Sankoff|1975}},<ref>{{citation
  | last1 = Chvatal | first1 = Václáv | author1-link = Václav Chvátal
  | last1 = Chvatal | first1 = Václáv | author1-link = Václav Chvátal
  | last2 = Sankoff | first2 = David | author2-link = David Sankoff
  | last2 = Sankoff | first2 = David | author2-link = David Sankoff
Line 514: Line 470:
  | 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> कई शोधकर्ताओं ने सबसे लंबी सामान्य अनुवर्ती लंबाई के व्यवहार की जांच की है जब दो दिए गए तार एक ही वर्णमाला से यादृच्छिक रूप से खींचे जाते हैं। जब वर्णमाला का आकार स्थिर होता है, तो LCS की अपेक्षित लंबाई दो स्ट्रिंग्स की लंबाई के समानुपाती होती है, और आनुपातिकता के स्थिरांक (वर्णमाला के आकार के आधार पर) च्वाटल-सैंकॉफ स्थिरांक के रूप में जाने जाते हैं। उनके सटीक मूल्य ज्ञात नहीं हैं, लेकिन उनके मूल्यों की ऊपरी और निचली सीमाएं सिद्ध हो चुकी हैं,<ref>{{citation
  | issue = 2 | year = 1975 | doi=10.2307/3212444| jstor = 3212444 | s2cid = 250345191 }}.</ref> कई शोधकर्ताओं ने सबसे लंबी सामान्य अनुवर्ती लंबाई के व्यवहार की जांच की है जब दो दिए गए तार एक ही वर्णमाला से यादृच्छिक रूप से खींचे जाते हैं। जब वर्णमाला का आकार स्थिर होता है, तो एलसीएस की अपेक्षित लंबाई दो तारों की लंबाई के समानुपाती होती है, और आनुपातिकता के स्थिरांक (वर्णमाला के आकार के आधार पर) को च्वताल-सैंकॉफ स्थिरांक के रूप में जाना जाता है। उनके सटीक मान ज्ञात नहीं हैं, लेकिन उनके मानों की ऊपरी और निचली सीमाएं सिद्ध हो चुकी हैं,<ref>{{citation
  | last = Lueker | first = George S.
  | last = Lueker | first = George S.
  | doi = 10.1145/1516512.1516519
  | doi = 10.1145/1516512.1516519
Line 524: Line 480:
  | volume = 56
  | volume = 56
  | year = 2009| s2cid = 7232681
  | year = 2009| s2cid = 7232681
  }}.</ref> और यह ज्ञात है कि वे वर्णमाला के आकार के वर्गमूल के विपरीत आनुपातिक रूप से बढ़ते हैं।<ref>{{citation
  }}.</ref> और यह ज्ञात है कि वे वर्णमाला के आकार के वर्गमूल के व्युत्क्रमानुपाती बढ़ते हैं।<ref>{{citation
  | last1 = Kiwi | first1 = Marcos
  | last1 = Kiwi | first1 = Marcos
  | last2 = Loebl | first2 = Martin
  | last2 = Loebl | first2 = Martin
Line 551: Line 507:
  | s2cid = 11390762
  | s2cid = 11390762
  }}.</ref>
  }}.</ref>
== यह भी देखें ==


 
* सबसे लंबे समय तक बढ़ने वाला क्रम - संख्याओं की एक सरणी में सबसे लंबे समय तक बढ़ने वाले क्रम को खोजने के लिए एल्गोरिथ्म
== यह भी देखें ==
* सबसे लंबा प्रत्यावर्ती क्रम
* [[सबसे लंबे समय तक बढ़ने वाला क्रम]]
* लेवेंसहाइट दूरी - स्ट्रिंग समानता के लिए कंप्यूटर विज्ञान मीट्रिक
* सबसे लंबा वैकल्पिक क्रम
* [[लेवेनशेटिन दूरी]]


== संदर्भ ==
== संदर्भ ==
Line 574: Line 529:
{{Strings |state=collapsed}}
{{Strings |state=collapsed}}


{{DEFAULTSORT:Longest Common Subsequence Problem}}[[Category: तारों पर समस्याएँ]] [[Category: साहचर्य]] [[Category: गतिशील प्रोग्रामिंग]] [[Category: बहुपद-समय की समस्याएँ]] [[Category: एनपी-पूर्ण समस्याएँ]]
{{DEFAULTSORT:Longest Common Subsequence Problem}}
 
 


[[Category: Machine Translated Page]]
[[Category:Articles with hatnote templates targeting a nonexistent page|Longest Common Subsequence Problem]]
[[Category:Created On 25/07/2023]]
[[Category:CS1 maint]]
[[Category:Collapse templates|Longest Common Subsequence Problem]]
[[Category:Created On 25/07/2023|Longest Common Subsequence Problem]]
[[Category:Lua-based templates|Longest Common Subsequence Problem]]
[[Category:Machine Translated Page|Longest Common Subsequence Problem]]
[[Category:Navigational boxes| ]]
[[Category:Navigational boxes without horizontal lists|Longest Common Subsequence Problem]]
[[Category:Pages with script errors|Longest Common Subsequence Problem]]
[[Category:Short description with empty Wikidata description|Longest Common Subsequence Problem]]
[[Category:Sidebars with styles needing conversion|Longest Common Subsequence Problem]]
[[Category:Template documentation pages|Documentation/doc]]
[[Category:Templates Vigyan Ready|Longest Common Subsequence Problem]]
[[Category:Templates generating microformats|Longest Common Subsequence Problem]]
[[Category:Templates that add a tracking category|Longest Common Subsequence Problem]]
[[Category:Templates that are not mobile friendly|Longest Common Subsequence Problem]]
[[Category:Templates that generate short descriptions|Longest Common Subsequence Problem]]
[[Category:Templates using TemplateData|Longest Common Subsequence Problem]]
[[Category:Wikipedia metatemplates|Longest Common Subsequence Problem]]
[[Category:एनपी-पूर्ण समस्याएँ|Longest Common Subsequence Problem]]
[[Category:गतिशील प्रोग्रामिंग|Longest Common Subsequence Problem]]
[[Category:तारों पर समस्याएँ|Longest Common Subsequence Problem]]
[[Category:बहुपद-समय की समस्याएँ|Longest Common Subsequence Problem]]
[[Category:साहचर्य|Longest Common Subsequence Problem]]

Latest revision as of 17:47, 10 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 हेडर बनाते हुए) के साथ रखा गया है।

LCS स्ट्रिंग्स
ε A G C A T
ε ε ε ε ε ε ε
G ε
A ε
C ε

इस तालिका का उपयोग गणना के प्रत्येक चरण के लिए एलसीएस अनुक्रम को संग्रहीत करने के लिए किया जाता है। दूसरे कॉलम और दूसरी पंक्ति को ε से भर दिया गया है, क्योंकि जब एक रिक्त अनुक्रम की तुलना एक गैर-रिक्त अनुक्रम से की जाती है, तो सबसे लंबा सामान्य अनुवर्ती हमेशा एक रिक्त अनुक्रम होता है।

LCS(R1, C1) प्रत्येक अनुक्रम में पहले एलिमेंटों की तुलना करके निर्धारित किया जाता है। G और A समान नहीं हैं, इसलिए यह LCS ("दूसरी संपत्ति का उपयोग करके" दो अनुक्रमों, LCS(R1, C0) और LCS(R0, C1) में से सबसे लंबा प्राप्त करता है। तालिका के अनुसार, ये दोनों रिक्त हैं, इसलिए LCS(R1, C1) भी रिक्त है, जैसा कि नीचे दी गई तालिका में दिखाया गया है। तीर इंगित करते हैं कि अनुक्रम ऊपर की दोनों कोशिकाओं, LCS(R0, C1) और बाईं ओर की कोशिका, LCS(R1, C0) से आता है।

LCS(R1, C2) का निर्धारण G और G की तुलना करके किया जाता है। वे मेल खाते हैं, इसलिए G को ऊपरी बाएँ क्रम में जोड़ा जाता है, LCS(R0, C1), जो (ε) है, दे रहा है (εG), जो कि (G) है .

LCS(R1, C3) के लिए, G और C मेल नहीं खाते। उपरोक्त क्रम रिक्त है; बाईं ओर वाले में एक एलिमेंट G है। इनमें से सबसे लंबे को चुनने पर LCS(R1, C3) (G) है। तीर बाईं ओर इंगित करता है, क्योंकि वह दो अनुक्रमों में सबसे लंबा है।

LCS(R1, C4), इसी प्रकार, (G) है।

LCS(R1, C5),, इसी तरह, (G) है।

"G" पंक्ति पूर्ण हुई
ε A G C A T
ε ε ε ε ε ε ε
G ε ε (G) (G) (G) (G)
A ε
C ε

LCS(R2, C1) के लिए, A की तुलना A से की जाती है। दोनों एलिमेंट मेल खाते हैं, इसलिए A को ε में जोड़ा जाता है, जिससे (A) मिलता है।

LCS(R2, C2) के लिए, A और G मेल नहीं खाते हैं, इसलिए LCS(R1, C2) में से सबसे लंबा, जो कि (G) है, और LCS(R2, C1), जो कि (A) है, का उपयोग किया जाता है। इस स्थिति में, उनमें से प्रत्येक में एक एलिमेंट होता है, इसलिए इस एलसीएस को दो अनुवर्ती दिए गए हैं: (A) और (G)।

LCS(R2, C3) के लिए, A, C से मेल नहीं खाता है। LCS(R2, C2) में अनुक्रम (A) और (G) सम्मिलित हैं; LCS(R1, C3) (G) है, जो पहले से ही LCS(R2, C2) में समाहित है। परिणाम यह है कि LCS(R2, C3) में दो अनुवर्ती, (A) और (G) भी सम्मिलित हैं।

LCS(R2, C4) के लिए, A, A से मेल खाता है, जो कि (GA) देते हुए ऊपरी बाएँ सेल से जुड़ा हुआ है।

LCS(R2, C5) के लिए, A, T से मेल नहीं खाता है। दो अनुक्रमों, (GA) और (G) की तुलना करने पर, सबसे लंबा (GA) है, इसलिए LCS(R2, C5) (GA) है।

"G" & "A" पंक्ति पूर्ण हुई
ε A G C A T
ε ε ε ε ε ε ε
G ε ε (G) (G) (G) (G)
A ε (A) (A) & (G) (A) & (G) (GA) (GA)
C ε

LCS(R3, C1) के लिए, C और A मेल नहीं खाते हैं, इसलिए LCS(R3, C1) को दो अनुक्रमों में से सबसे लंबा अनुक्रम मिलता है, (A)।

LCS(R3, C2) के लिए, C और G मेल नहीं खाते। LCS(R3, C1) और LCS(R2, C2) दोनों में एक एलिमेंट है। परिणाम यह है कि LCS(R3, C2) में दो अनुवर्ती, (A) और (G) सम्मिलित हैं।

LCS(R3, C3) के लिए, C और C मेल खाते हैं, इसलिए C को LCS(R2, C2) में जोड़ा जाता है, जिसमें दो अनुवर्ती (A) और (G) होते हैं, जो (AC) और (GC) देते हैं।

LCS(R3, C4) के लिए, C और A मेल नहीं खाते। LCS(R3, C3)), जिसमें (AC) और (GC), और LCS(R2, C4), जिसमें (GA) सम्मिलित है, को मिलाने पर कुल तीन अनुक्रम मिलते हैं: (AC), (GC), और (GA) ).

अंततः, LCS(R3, C5) के लिए, C और T मेल नहीं खाते। परिणाम यह है कि LCS(R3, C5) में तीन अनुक्रम, (AC), (GC), और (GA) भी सम्मिलित हैं।

पूर्ण LCS तालिका
ε 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)

अंतिम परिणाम यह है कि अंतिम सेल में (AGCAT) और (GAC) के सभी सबसे लंबे अनुवर्ती सामान्य सम्मिलित हैं; ये (AC), (GC), और (GA) हैं। तालिका उपसर्गों की प्रत्येक संभावित जोड़ी के लिए सबसे लंबे सामान्य अनुवर्ती को भी दर्शाती है। उदाहरण के लिए, (AGC) और (GA) के लिए, सबसे लंबे सामान्य अनुवर्ती (A) और (G) हैं।

ट्रेसबैक दृष्टिकोण

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

वास्तविक अनुवर्ती एक "ट्रेसबैक" प्रक्रिया में निकाले जाते हैं जो तालिका में अंतिम सेल से शुरू होकर पीछे की ओर तीरों का अनुसरण करता है। जब लंबाई कम हो जाती है, तो अनुक्रमों में एक सामान्य एलिमेंट होना चाहिए। जब किसी कक्ष में दो तीर दिखाए जाते हैं तो कई पथ संभव होते हैं। इस तरह के विश्लेषण के लिए नीचे तालिका दी गई है, जिसमें उन कोशिकाओं में रंगीन संख्याएँ हैं जहाँ लंबाई घटने वाली है। बोल्ड नंबर अनुक्रम (GA) का पता लगाते हैं।[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]

जब केवल सम्मिलन और विलोपन की अनुमति है (कोई प्रतिस्थापन नहीं), या जब प्रतिस्थापन की लागत सम्मिलन या विलोपन की लागत से दोगुनी है, तो संपादन दूरी है:

डायनामिक प्रोग्रामिंग समाधान के लिए कोड

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]

   function LCSLength(X[1..m], Y[1..n])
    C = array(0..m, 0..n)
    for i := 0..m
        C[i,0] = 0
    for j := 0..n
        C[0,j] = 0
    for i := 1..m
        for j := 1..n
            if X[i] = Y[j]
                C[i,j] := C[i-1,j-1] + 1
            else
                C[i,j] := max(C[i,j-1], C[i-1,j])
    return C[m,n]

वैकल्पिक रूप से, मेमोइज़ेशन का उपयोग किया जा सकता है।

LCS पढ़ना

निम्नलिखित फ़ंक्शन गणना करते समय लिए गए विकल्पों को बैक ट्रैकिंग करता है C मेज़। यदि उपसर्गों में अंतिम वर्ण समान हैं, तो उन्हें LCS में होना चाहिए। यदि नहीं, तो जांचें कि किस चीज़ ने रखने का सबसे बड़ा LCS दिया और , और वही चुनाव करें। यदि वे समान रूप से लंबे हों तो बस एक चुनें। फ़ंक्शन को कॉल करें i=m और j=n.

function backtrack(C[0..m,0..n], X[1..m], Y[1..n], i, j)
    if i = 0 or j = 0
        return ""
    if  X[i] = Y[j]
        return backtrack(C, X, Y, i-1, j-1) + X[i]
    if C[i,j-1] > C[i-1,j]
        return backtrack(C, X, Y, i, j-1)
    return backtrack(C, X, Y, i-1, j)

सभी LCS को पढ़ना

अगर चुन रहे हैं और समान रूप से लंबा परिणाम देगा, दोनों परिणामी अनुवर्ती पढ़ें। इसे इस फ़ंक्शन द्वारा एक सेट के रूप में लौटाया जाता है। ध्यान दें कि यह फ़ंक्शन बहुपद नहीं है, क्योंकि यदि तार समान हैं तो यह लगभग हर चरण में शाखाबद्ध हो सकता है।

function backtrackAll(C[0..m,0..n], X[1..m], Y[1..n], i, j)
    if i = 0 or j = 0
        return {""}
    if X[i] = Y[j]
        return {Z + X[i] for all Z in backtrackAll(C, X, Y, i-1, j-1)}
    R := {}
    if C[i,j-1] ≥ C[i-1,j]
        R := backtrackAll(C, X, Y, i, j-1)
    if C[i-1,j] ≥ C[i,j-1]
        R := R ∪ backtrackAll(C, X, Y, i-1, j)
    return R

diff प्रिंट करें

यह फ़ंक्शन C मैट्रिक्स के माध्यम से बैकट्रैक करेगा, और दो अनुक्रमों के बीच अंतर प्रिंट करेगा। ध्यान दें कि यदि आप और< को नीचे > और से बदलते हैं तो आपको एक अलग उत्तर मिलेगा।

function printDiff(C[0..m,0..n], X[1..m], Y[1..n], i, j)
    if i >= 0 and j >= 0 and X[i] = Y[j]
        printDiff(C, X, Y, i-1, j-1)
        print "  " + X[i]
    else if j > 0 and (i = 0 or C[i,j-1] ≥ C[i-1,j])
        printDiff(C, X, Y, i, j-1)
        print "+ " + Y[j]
    else if i > 0 and (j = 0 or C[i,j-1] < C[i-1,j])
        printDiff(C, X, Y, i-1, j)
        print "- " + X[i]
    else
        print ""

उदाहरण

मान लीजिये "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 तुलनाएं करने की आवश्यकता होगी। वास्तविक दुनिया के अधिकांश मामलों में, विशेष रूप से स्रोत कोड अंतर और पैच में, फ़ाइलों की प्रारम्भ और अंत शायद ही कभी बदलते हैं, और लगभग निश्चित रूप से एक ही समय में दोनों नहीं। यदि अनुक्रम के मध्य में केवल कुछ आइटम बदले गए हैं, तो प्रारम्भ और अंत को हटाया जा सकता है। यह न केवल मैट्रिक्स के लिए मेमोरी आवश्यकताओं को कम करता है, बल्कि की जाने वाली तुलनाओं की संख्या को भी कम करता है।

function LCS(X[1..m], Y[1..n])
    start := 1
    m_end := m
    n_end := n
    trim off the matching items at the beginning
    while start ≤ m_end and start ≤ n_end and X[start] = Y[start]
        start := start + 1
    trim off the matching items at the end
    while start ≤ m_end and start ≤ n_end and X[m_end] = Y[n_end]
        m_end := m_end - 1
        n_end := n_end - 1
    C = array(start-1..m_end, start-1..n_end)
    only loop over the items that have changed
    for i := start..m_end
        for j := start..n_end
            the algorithm continues as before ...

सर्वोत्तम स्थिति में, बिना किसी बदलाव वाले अनुक्रम में, यह अनुकूलन सी मैट्रिक्स की आवश्यकता को समाप्त कर देगा। सबसे खराब स्थिति में, अनुक्रम में सबसे पहले और आखिरी आइटम में बदलाव के बाद केवल दो अतिरिक्त तुलनाएं की जाती हैं।

तुलना समय कम करें

अनुभवहीन एल्गोरिथ्म द्वारा लिया गया अधिकांश समय अनुक्रमों में वस्तुओं के बीच तुलना करने में खर्च होता है। स्रोत कोड जैसे पाठ अनुक्रमों के लिए, आप एकल वर्णों के बजाय पंक्तियों को अनुक्रम एलिमेंटों के रूप में देखना चाहते हैं। इसका अर्थ एल्गोरिदम में प्रत्येक चरण के लिए अपेक्षाकृत लंबी स्ट्रिंग की तुलना हो सकता है। दो अनुकूलन किए जा सकते हैं जो इन तुलनाओं में लगने वाले समय को कम करने में सहायता कर सकते हैं।

स्ट्रिंग्स को हैश में कम करें

अनुक्रमों में स्ट्रिंग के आकार को कम करने के लिए हैश फंकशन या चेकसम का उपयोग किया जा सकता है। अर्थात्, स्रोत कोड के लिए जहां औसत पंक्ति 60 या अधिक वर्ण लंबी है, उस पंक्ति के लिए हैश या चेकसम केवल 8 से 40 वर्ण लंबा हो सकता है। इसके अतिरिक्त, हैश और चेकसम की यादृच्छिक प्रकृति यह गारंटी देगी कि तुलना तेजी से शॉर्ट-सर्किट होगी, क्योंकि स्रोत कोड की लाइनें प्रारम्भ में शायद ही कभी बदली जाएंगी।

इस अनुकूलन में तीन प्राथमिक कमियाँ हैं। सबसे पहले, दो अनुक्रमों के लिए हैश की पूर्व-गणना करने के लिए पहले से ही काफी समय खर्च करने की आवश्यकता है। दूसरा, नए हैशेड अनुक्रमों के लिए अतिरिक्त मेमोरी आवंटित करने की आवश्यकता है। हालाँकि, यहां उपयोग किए गए अनुभवहीन एल्गोरिदम की तुलना में, ये दोनों कमियां अपेक्षाकृत न्यूनतम हैं।

तीसरा दोष टकराव का है। चूँकि चेकसम या हैश के अद्वितीय होने की गारंटी नहीं है, इसलिए इस बात की बहुत कम संभावना है कि दो अलग-अलग वस्तुओं को एक ही हैश में घटाया जा सकता है। सोर्स कोड में यह संभव नहीं है, लेकिन यह संभव है। इसलिए एक क्रिप्टोग्राफ़िक हैश इस अनुकूलन के लिए कहीं बेहतर अनुकूल होगा, क्योंकि इसकी एन्ट्रापी एक साधारण चेकसम की तुलना में काफी अधिक होगी। हालाँकि, लाभ छोटे अनुक्रम लंबाई के लिए क्रिप्टोग्राफ़िक हैश की सेटअप और कम्प्यूटेशनल आवश्यकताओं के लायक नहीं हो सकता है।

आवश्यक स्पेस कम करें

यदि केवल LCS की लंबाई आवश्यक है, मैट्रिक्स को मैट्रिक्स, या वेक्टर तक कम किया जा सकता है क्योंकि गतिशील प्रोग्रामिंग दृष्टिकोण के लिए मैट्रिक्स के केवल वर्तमान और पिछले कॉलम की आवश्यकता होती है। हिर्शबर्ग का एल्गोरिदम समान द्विघात समय और रैखिक स्पेस सीमा में इष्टतम अनुक्रम के निर्माण की अनुमति देता है।[8]

कैशे की कमी कम करें

चौधरी और रामचंद्रन ने एक द्विघात-समय रैखिक-स्पेस एल्गोरिदम तैयार किया[9][10] एक इष्टतम अनुक्रम के साथ LCS लंबाई खोजने के लिए जो अपने बेहतर कैश प्रदर्शन के कारण व्यवहार में हिर्शबर्ग के एल्गोरिदम से तेज़ चलता है।[9] कैश-ओब्लिवियस आदर्शीकृत कैश मॉडल के तहत एल्गोरिदम में एक असम्बद्ध रूप से इष्टतम कैश जटिलता है।[11] रोचक बात यह है कि एल्गोरिथ्म स्वयं कैश-अनभिज्ञ है[11] इसका मतलब यह है कि यह मशीन के कैश पैरामीटर (उदाहरण के लिए, कैश आकार और कैश लाइन आकार) के आधार पर कोई विकल्प नहीं बनाता है।

आगे अनुकूलित एल्गोरिदम

कई एल्गोरिदम उपस्थित हैं जो प्रस्तुत गतिशील प्रोग्रामिंग दृष्टिकोण की तुलना में तेज़ चलते हैं। उनमें से एक हंट-ज़िमांस्की एल्गोरिदम है, जो सामान्यतः समय (के लिए) में चलता है, जहां दो अनुक्रमों के बीच मिलान की संख्या है।[12] गठबंधन हुई वर्णमाला के आकार की समस्याओं के लिए, लॉगरिदमिक कारक द्वारा गतिशील प्रोग्रामिंग एल्गोरिदम के चलने के समय को कम करने के लिए चार रूसी की विधि का उपयोग किया जा सकता है।[13]

यादृच्छिक स्ट्रिंग्स पर व्यवहार

च्वाटल और सैंकोफ़ (1975) से प्रारम्भ करते हुए,[14] कई शोधकर्ताओं ने सबसे लंबी सामान्य अनुवर्ती लंबाई के व्यवहार की जांच की है जब दो दिए गए तार एक ही वर्णमाला से यादृच्छिक रूप से खींचे जाते हैं। जब वर्णमाला का आकार स्थिर होता है, तो एलसीएस की अपेक्षित लंबाई दो तारों की लंबाई के समानुपाती होती है, और आनुपातिकता के स्थिरांक (वर्णमाला के आकार के आधार पर) को च्वताल-सैंकॉफ स्थिरांक के रूप में जाना जाता है। उनके सटीक मान ज्ञात नहीं हैं, लेकिन उनके मानों की ऊपरी और निचली सीमाएं सिद्ध हो चुकी हैं,[15] और यह ज्ञात है कि वे वर्णमाला के आकार के वर्गमूल के व्युत्क्रमानुपाती बढ़ते हैं।[16] सबसे लंबी सामान्य अनुवर्ती समस्या के सरलीकृत गणितीय मॉडल को ट्रेसी-विडोम वितरण द्वारा नियंत्रित दिखाया गया है।[17]

यह भी देखें

  • सबसे लंबे समय तक बढ़ने वाला क्रम - संख्याओं की एक सरणी में सबसे लंबे समय तक बढ़ने वाले क्रम को खोजने के लिए एल्गोरिथ्म
  • सबसे लंबा प्रत्यावर्ती क्रम
  • लेवेंसहाइट दूरी - स्ट्रिंग समानता के लिए कंप्यूटर विज्ञान मीट्रिक

संदर्भ

  1. David Maier (1978). "परवर्ती और अतिपरवर्ती पर कुछ समस्याओं की जटिलता". J. ACM. ACM Press. 25 (2): 322–336. doi:10.1145/322063.322075. S2CID 16120634.
  2. 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. 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)
  4. Ronald I. Greenberg (2003-08-06). "सबसे लंबे सामान्य अनुवर्ती की संख्या पर सीमा". arXiv:cs.DM/0301030.
  5. 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.
  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)
  7. 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.
  8. Hirschberg, D. S. (1975). "अधिकतम सामान्य अनुवर्ती की गणना के लिए एक रैखिक अंतरिक्ष एल्गोरिदम". Communications of the ACM. 18 (6): 341–343. doi:10.1145/360825.360861. S2CID 207694727.
  9. 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.
  10. 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. 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.
  12. Apostolico, Alberto; Galil, Zvi (1997-05-29). पैटर्न मिलान एल्गोरिदम. ISBN 9780195354348.
  13. 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.
  14. 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.
  15. 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.
  16. 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.
  17. 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.


बाहरी संबंध