कौन सा स्ट्रिंग खोज एल्गोरिथ्म वास्तव में सबसे तेज है?


27

मैं कुछ समय के लिए अटक गया हूं जिस पर सबसे तेज स्ट्रिंग खोज एल्गोरिथ्म है, कई राय सुनी, लेकिन अंत में मुझे यकीन नहीं है।

मैंने कुछ लोगों को यह कहते हुए सुना है कि सबसे तेज़ एल्गोरिथ्म बोयर-मूर है और कुछ कह रहे हैं कि नुथ-मॉरिस-प्रैट वास्तव में तेज़ है।

मैंने उन दोनों की जटिलता को देखा है लेकिन वे ज्यादातर एक जैसे ही दिखते हैं O(n+m)। मैंने पाया है कि सबसे खराब स्थिति में बॉयर-मूर की O(nm)नथ-मॉरिस-प्रैट की तुलना में एक जटिलता है जिसमें ओ (एम + 2 * एन) है। जहाँ n = पाठ की लंबाई और m = पैटर्न की लंबाई।

जहां तक ​​मुझे पता है कि बॉयर-मूर के पास एक रैखिक-सबसे खराब स्थिति है, अगर मैं गैलिल नियम का उपयोग करूंगा।

मेरा प्रश्न, ओवर ऑल जो वास्तव में सबसे तेज स्ट्रिंग सर्च एल्गोरिथ्म है (इस सवाल में सभी संभावित स्टिंग एल्गोरिदम शामिल हैं न कि केवल बॉयर-मूर और नूथ-मॉरिस-प्रैट)।

संपादित करें: इस उत्तर के कारण

मैं वास्तव में क्या देख रहा हूँ:

एक पाठ को देखते हुए Tऔर एक पैटर्न Pमैं सब दिखावे खोजने के लिए Pमें T

इसके अलावा पी और टी की लंबाई है और [1,2 000 000]कार्यक्रम को 0.15 सेकंड के तहत चलाना है।

मुझे पता है कि केएमपी और राबिन-कार्प समस्या पर 100% अंक प्राप्त करने के लिए पर्याप्त हैं, लेकिन मैं एक के लिए बॉयर-मूर को लागू करने और लागू करना चाहता था। इस प्रकार की पैटर्न खोज के लिए कौन सा सबसे अच्छा होगा?


6
जब आपने अपनी पसंद की भाषा में इनका परीक्षण किया तो आपको क्या मिला?
वाल्टर

4
कुछ परीक्षणों पर बोयर-मूर अन्य केएमपी पर बेहतर था, लेकिन मुझे यकीन नहीं है कि मुझे उनमें से "सबसे अच्छा" कार्यान्वयन है। पसंद की भाषा के लिए के रूप में यह टैग में है: सी ++ (सुनिश्चित नहीं है कि अगर आपने देखा कि जब से आपने "पसंद की भाषा" लिखी है)। PS मुझे यकीन नहीं है कि अगर मैंने सबसे अच्छे परीक्षणों पर परीक्षण किया।
वंदामों ताइगी


नथ-मॉरिस-प्रैट जिसमें ओ (एम + 2 * एन) है ... आपका मतलब ओ (एम + एन) है।
जूल्स

एक सभ्य एल्गोरिथम जटिलता के साथ एक उठाओ और फिर हाथ में एक प्रोफाइलर के साथ इसे बाहर से सूक्ष्म ट्यून करें - हमेशा मेरे लिए काम किया। :-D

जवाबों:


38

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

यहां खोज प्रकारों पर कुछ विशिष्ट विचार दिए गए हैं:

  • बॉयर-मूर: पैटर्न का पूर्व-विश्लेषण करके और दाएं-बाएं से तुलना करके काम करता है। यदि कोई बेमेल होता है, तो प्रारंभिक विश्लेषण का उपयोग यह निर्धारित करने के लिए किया जाता है कि पैटर्न को खोजे जा रहे पाठ को कितना दूर स्थानांतरित किया जा सकता है। यह लंबे खोज पैटर्न के लिए विशेष रूप से अच्छी तरह से काम करता है। विशेष रूप से, यह उप-रैखिक हो सकता है, क्योंकि आपको अपने पाठ के हर एक चरित्र को पढ़ने की आवश्यकता नहीं है।

  • नूथ-मॉरिस-प्रैट: पैटर्न का भी पूर्व-विश्लेषण करता है, लेकिन पैटर्न के प्रारंभिक भाग में जो कुछ भी पहले से मिलान किया गया था उसे फिर से उपयोग करने से बचने की कोशिश करता है। यह काफी अच्छी तरह से काम कर सकता है, अगर आपका वर्णमाला छोटा है (f.ex. डीएनए आधार), जैसा कि आपको एक उच्च मौका मिलता है कि आपके खोज पैटर्न में पुन: उपयोग करने योग्य उपपट्टियाँ होती हैं।

  • अहो-कोरासिक: बहुत अधिक प्रीप्रोसेसिंग की आवश्यकता है, लेकिन कई पैटर्न के लिए ऐसा करता है। यदि आप जानते हैं कि आप बार-बार एक ही खोज पैटर्न की तलाश करेंगे, तो यह दूसरे की तुलना में बहुत बेहतर है, क्योंकि आपको केवल एक बार प्रतिमानों का विश्लेषण करना है, न कि एक बार प्रति खोज।

इसलिए, सीएस में हमेशा की तरह, समग्र सर्वश्रेष्ठ का कोई निश्चित उत्तर नहीं है । बल्कि हाथ में नौकरी के लिए सही उपकरण चुनने की बात है।

अपने सबसे खराब मामले पर एक और ध्यान दें: उस सबसे खराब स्थिति को बनाने के लिए आवश्यक खोजों के प्रकारों पर विचार करें और इस बारे में पूरी तरह सोचें कि क्या ये वास्तव में आपके मामले में प्रासंगिक हैं। उदाहरण के लिए, O(mn)बॉयर-मूर एल्गोरिथम की सबसे खराब स्थिति एक खोज पैटर्न और एक पाठ से उपजी है, जिसमें से प्रत्येक केवल एक वर्ण (जैसे खोजने aaaमें aaaaaaaaaaaaaaaaaaaaa) का उपयोग करता है - क्या आपको वास्तव में उस तरह की खोजों के लिए तेज़ होना चाहिए?


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

और हां मुझे इस तरह की खोजों के लिए भी तेज रहने की जरूरत है
वंडामन टैगी

1

हालाँकि मुझे इस प्रश्न का उत्तर देने में थोड़ी देर हो गई है, लेकिन मुझे लगता Z-Algorithmहै कि यह किसी भी समकक्ष की तुलना में बहुत तेज है। इसकी सबसे खराब स्थिति O (m + n) है और इसके लिए पैटर्न / पाठ के पूर्व-निर्धारण की आवश्यकता नहीं है। अन्य एल्गोरिदम की तुलना में इसे कोड करना भी बहुत आसान है।

यह निम्नलिखित तरीके से काम करता है।

उदाहरण के लिए, एक स्ट्रिंग है S ='abaaba'। हम के लिए z(i)मूल्यों को खोजने के लिए कर रहे हैं i=0 to len(S)-1। स्पष्टीकरण में जाने से पहले, मुझे कुछ परिभाषाएँ देनी चाहिए।

z(i)= नहीं। के उपसर्ग के वर्णों के उपसर्ग से Sमेल खाता है s(i)

s(i)= का ithप्रत्यय S

निम्नलिखित के लिए s(i)मान हैं s = 'abaaba'

s(0) = 'abaaba' = S
s(1) = 'baaba'
s(2) = 'aaba'
s(3) = 'aba'
s(4) = 'ba'
s(5) = 'a'

Z मान क्रमशः हैं

z(0) = 6 = length(S)
z(1) = 0
z(2) = 1
z(3) = 3
z(4) = 0
z(5) = 1

एल्गोरिथ्म की विस्तृत समझ के लिए, निम्नलिखित लिंक देखें।

http://codeforces.com/blog/entry/3107

https://www.youtube.com/watch?v=MFK0WYeVEag

अब zकिसी भी पूर्व-प्रसंस्करण ओवरहेड के बिना सभी मूल्यों को खोजने के लिए O (N) लेता है । अब आप सोच रहे होंगे कि आप किसी दिए गए स्ट्रिंग में पैटर्न का मिलान करने के लिए इस तर्क का उपयोग कैसे कर सकते हैं?

एक उदाहरण के साथ देखते हैं। पैटर्न (P):, abaटेक्स्ट (T) aacbabcabaad:।

इसे P $ T के रूप में रखें। ( $- कोई भी वर्ण जो पैटर्न या पाठ में प्रकट नहीं होता है। मैं $थोड़ी देर में महत्व के लिए आता हूँ ।)

P$T = aba$aacbabcabaad

हम जानते हैं len(P)= ३।

के सभी z मान P$Tहैं

z(0) = 16 = len(P$T)
z(1) = 0
z(2) = 1
z(3) = 0
z(4) = 1
z(5) = 1
z(6) = 0
z(7) = 0
z(8) = 2
z(9) = 0
z(10) = 0
z(11) = 3
z(12) = 0
z(13) = 1
Z(14) = 1
Z(15) = 0

अब जो z(i)= len(P)Ans = 11.तो हमारा पैटर्न Ans-len(P)-1= पर मौजूद है 7। चरित्र के -1लिए $है।

अब क्यों $या इस तरह का कोई विशेष चरित्र महत्वपूर्ण है। पर विचार करें P = 'aaa'और T = 'aaaaaaa'। विशेष चरित्र के बिना, सभी z(i)में वृद्धिशील मूल्य होंगे। एक अभी भी नीचे दिए गए सूत्रों के साथ पाठ में पैटर्न की स्थिति पा सकता है:

शर्त: z(i)> = len(P)और स्थिति Ans-len(P):। लेकिन इस मामले में स्थिति थोड़ी मुश्किल और भ्रामक हो जाती है। मैं व्यक्तिगत रूप से विशेष चरित्र तकनीक का उपयोग करना पसंद करता हूं।


1
क्या आप इसे अपने यहाँ समझा सकते हैं? बाहरी साइटों के लिंक होने का उपयोग विस्तृत करने के लिए किया जा सकता है, लेकिन एक उत्तर का मूल दूसरी साइट के लिंक का पालन करने के बजाय उत्तर में ही होना चाहिए।

Z- एल्गोरिथ्म मूलतः kmp के समान है। मुझे संदेह है कि यह बहुत तेज है।
थॉमस अहले

2
मैं @ThomasAhle से सहमत हूं। कम्प्यूटिंग z है preprocessing। हालांकि यह एक अच्छी व्याख्या है। मैंने O(n)इस उत्तर के कारण केएमपी प्री-प्रोसेसिंग से जेड प्री-प्रोसेसिंग में बदलने का एक तरीका रखा । यहाँ
leewz

-1

वर्चुअल एड्रेसिंग (अक्षरों की ओर इशारा करते हुए) के रूप में सॉफ्टवेयर में लागू सामग्री पता योग्य मेमोरी का उपयोग करें ।

यह एक औसत स्ट्रिंग मैचिंग एल्गोरिथ्म के लिए बहुत बढ़िया है।

सीएएम एक साथ बड़ी संख्या में प्रतिमानों का मिलान कर सकता है, लगभग 128-अक्षर प्रतिमानों तक (यदि वे ASCII हैं; यदि वे यूनिकोड केवल 64 हैं)। और यह स्ट्रिंग में पत्र की लंबाई के अनुसार एक कॉल है जिसे आप मैच करना चाहते हैं और अधिकतम पैटर्न लंबाई की प्रति मेमोरी से एक यादृच्छिक रीड पढ़ें। इसलिए यदि आप एक 100,000 अक्षर स्ट्रिंग का विश्लेषण कर रहे थे, एक साथ 90,000,000 पैटर्न के साथ (जो कि पैटर्न की एक गिनती को स्टोर करने के लिए लगभग 128 GiB लेगा), तो यह RAM से 12,800,000 यादृच्छिक रीड्स लेगा, इसलिए यह 1ms में होगा।

यहां बताया गया है कि वर्चुअल एड्रेसिंग कैसे काम करता है।

यदि मैं 256 स्टार्टऑफ पते के साथ शुरू करता हूं, जो पहले अक्षर का प्रतिनिधित्व करता है, तो ये पत्र अगले अक्षरों के 256 को इंगित करते हैं। यदि कोई पैटर्न अनुपस्थित है, तो आप इसे संग्रहीत नहीं करते हैं।

इसलिए अगर मैं अक्षरों को अक्षरों से जोड़ता हूं, तो यह वर्चुअल एड्रेसिंग की ओर इशारा करते हुए वर्चुअल एड्रेसिंग के 128 स्लाइस होने जैसा है।

यह काम करेगा - लेकिन एक साथ मिलान करने के लिए 900,000,000 पैटर्न प्राप्त करने के लिए, इसमें जोड़ने के लिए एक आखिरी चाल है - और यह इस तथ्य का लाभ उठा रहा है कि आप इन पत्र बफ़र्स के बहुत सारे पुन: उपयोग के साथ शुरू करते हैं, लेकिन बाद में इसे बाहर निकालते हैं। यदि आप सभी 256 वर्णों को आवंटित करने के बजाय सामग्री को सूचीबद्ध करते हैं, तो यह बहुत कम हो जाता है, और आपको 100 गुना क्षमता में वृद्धि होगी, क्योंकि आपको मूल रूप से हर अक्षर सूचक बफर में केवल 1 अक्षर का उपयोग किया जाता है (जिसे मैंने डब किया था) पलायन')।

यदि आप निकटतम-पड़ोसी स्ट्रिंग मैच प्राप्त करना चाहते हैं, तो आपके पास इनमें से कई समानांतर चल रहे हैं और आप एक पदानुक्रम में एकत्र करते हैं, इसलिए आप अपनी त्रुटि को निष्पक्ष रूप से फैलाते हैं। अगर आप सिर्फ एक के साथ निकटतम-पड़ोसी की कोशिश करते हैं, तो आप पेड़ की शुरुआत के पक्षपाती हैं।


4
@MagnusRobertCarlWoot ने कहा कि आपके पास ravcer81 जैसा ही गावतार है, यह या तो हैश कोड टकराने का एक खगोलीय संयोग है या आपके पास एक ही ईमेल पता है। यदि आप दोनों खातों के पीछे एक ही व्यक्ति हैं, तो आपको उन्हें मर्ज करने के लिए "हमसे संपर्क करें" फ़ॉर्म का उपयोग करना चाहिए ताकि आपको इस उत्तर पर उत्थान के माध्यम से प्राप्त प्रतिष्ठा का उचित श्रेय मिले।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.