O (n) में प्रत्यय सरणियों का उपयोग करते हुए एक स्ट्रिंग का सबसे छोटा लेक्सोग्राफिक रोटेशन


9

मैं एसीएम 2003 से समस्या को उद्धृत करूंगा:

लंबाई n (1 <= n <= 100000) की एक स्ट्रिंग पर विचार करें। इसका न्यूनतम लेक्सोग्राफिक रोटेशन निर्धारित करें। उदाहरण के लिए, स्ट्रिंग "अलबाला" के घुमाव हैं:

alabala

Labalaa

abalaal

balaala

alaalab

laalaba

aalabal

और उनमें से सबसे छोटा है "नीला"।

समाधान के लिए - मुझे पता है कि मुझे एक प्रत्यय सरणी का निर्माण करने की आवश्यकता है - और मान लें कि मैं ओ (एन) में ऐसा कर सकता हूं। मेरा प्रश्न अभी भी है, मैं O (n) में सबसे छोटी घुमाव कैसे पा सकता हूं? (n = एक स्ट्रिंग की लंबाई)

मुझे इस समस्या में बहुत दिलचस्पी है और अभी भी मुझे किसी भी तरह से समाधान नहीं मिला है। मुझे अवधारणा में और अधिक दिलचस्पी है और समस्या को हल करने के लिए और कंक्रीट कार्यान्वयन में नहीं।

नोट: न्यूनतम रोटेशन का मतलब उसी क्रम में होता है जैसे अंग्रेजी शब्दकोश में - "डावर" "शब्द" से पहले होता है क्योंकि d, w से पहले होता है।

संपादित करें: प्रत्यय सरणी निर्माण में O (N) लगता है

पिछले संस्करण: मुझे लगता है कि मुझे एक समाधान मिला !!! अगर मैं सिर्फ दो तार मिला दूं तो क्या होगा? तो अगर स्ट्रिंग "अलाबाला" है, तो नया तार मुझे "अलाबालाबाला" कहेगा और अब मैं इसका एक प्रत्यय सरणी (O (2n) = O (n) में बनाऊंगा) और पहला प्रत्यय मिला? मुझे लगता है कि यह सही हो सकता है। तुम क्या सोचते हो? धन्यवाद!


आप "न्यूनतम" को कैसे परिभाषित करते हैं? मीट्रिक का उपयोग क्या है (शायद यह स्पष्ट है लेकिन मैं विशेषज्ञ नहीं हूं)?
जियोर्जियो

नोट के लिए धन्यवाद! मुझे लगा कि रोटेशन न्यूनतम (न्यूनतम ऑफसेट) होना चाहिए, न कि रोटेशन wrt lexicographic क्रम का परिणाम।
जियोर्जियो

मुझे अभी भी कुछ याद नहीं है: क्या जटिलता में शामिल प्रत्यय सरणी का निर्माण और छंटनी है? मुझे लगता है कि यह सरणी बनाने और इसे सॉर्ट करने में O (n) से अधिक लगता है।
जियोर्जियो

मुझे लगता है कि मूल स्ट्रिंग को दो बार दोहराने का विचार बहुत अच्छा है! तब आप O (2n) = O (n) में प्रत्यय सरणी का निर्माण कर सकते हैं। लेकिन आपको न्यूनतम खोजने के लिए इसे क्रमबद्ध करने की आवश्यकता नहीं है? यह ओ (एन) से अधिक की आवश्यकता है, है ना?
जियोर्जियो

@ जियोर्जियो अच्छी तरह से, प्रत्यय सरणी पहले से ही हल किए गए प्रत्ययों को रखती है । और एक और नोट, शायद थोड़ा ऑफटॉपिक - यह मत भूलो कि सॉर्टिंग को ओ (एन) में भी किया जा सकता है, कुछ वस्तुओं के साथ छंटनी की गई वस्तुओं (उदाहरण के लिए मूलांक सॉर्ट की जांच करें)
टॉमी

जवाबों:


5

लंबाई N की एक स्ट्रिंग के सभी घुमावों का निर्माण करने के लिए एक सरल ट्रिक है स्ट्रिंग को स्वयं से जोड़ना।

फिर इस 2N- लंबाई स्ट्रिंग के प्रत्येक एन-लंबाई विकल्प स्ट्रिंग का मूल स्ट्रिंग है।

"लेक्सिकोग्राफ़िक रूप से न्यूनतम" सबस्ट्रिंग का पता लगाना आपके O (N) ट्री निर्माण के साथ किया जाता है।


0

मुझे पूरा यकीन है कि एक प्रत्यय सरणी में निहित जानकारी आपको O (n) में लाने में मदद करने के लिए पर्याप्त नहीं है, लेकिन अधिकतम आप O (n log n) में मदद कर सकते हैं। प्रत्ययों के इस परिवार पर विचार करें:

a
aba
abacaba
abacabadabacaba
abacabadabacabaeabacabadabacaba
...

आप पिछले प्रत्यय (अबा कहो) को ले कर अगले प्रत्यय का निर्माण करते हैं, अगले वर्ण का उपयोग नहीं करते हैं और फिर पिछले प्रत्यय को जोड़ते हैं (इसलिए अबा -> अबा सी अबा)।

अब इन तारों पर विचार करें (जोर देने के लिए स्थान जोड़ा गया है, लेकिन स्ट्रिंग का हिस्सा नहीं है):

ad abacaba
bd abacaba
cd abacaba

इन तीन स्ट्रिंग्स के लिए, प्रत्यय सरणी की शुरुआत इस तरह दिखाई देगी:

a
aba
abacaba
(other suffixes)

जाना पहचाना? पाठ्यक्रम के ये तार इस प्रत्यय सरणी बनाने के लिए सिलवाया गया है। अब, प्रारंभिक अक्षर (ए, बी या सी) के आधार पर, 'सही' सूचकांक (आपकी समस्या का समाधान) या तो पहले, दूसरे या तीसरे प्रत्यय से ऊपर की सूची में है।

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

हालांकि मेरे पास कोई कठिन सबूत नहीं है, यह दृढ़ता से मुझे सुझाव देता है कि आपके पास अपने लेक्सिकोग्राफिक ऑर्डर के लिए सरणी में इन पहले तीन सूचकांकों के अनुरूप घुमाव की तुलना करने के अलावा कोई विकल्प नहीं है, जिसका अर्थ है कि आपको कम से कम हे (n) की आवश्यकता होगी इसके लिए लॉग एन) समय (वैकल्पिक पहले वर्णों की संख्या के रूप में - हमारे मामले में 3 - लॉग एन है, और दो तारों की तुलना में ओ (एन) समय लगता है)।

यह O (n) एल्गोरिथ्म की संभावना को खारिज नहीं करता है। मुझे केवल संदेह है कि एक प्रत्यय सरणी आपको इस चलने के समय को प्राप्त करने में मदद करता है।


0

सबसे छोटा घुमाव वह है जो प्रत्यय सरणी से कुछ प्रत्यय से शुरू होता है। प्रत्यय क्रमबद्ध रूप से दिए गए हैं। यह आपको एक बड़ा जम्पस्टार्ट देता है:

  • आप जानते हैं कि एक बार आपको ऐसा k मिलता है कि प्रत्यय k से शुरू होने वाला रोटेशन , प्रत्यय k +1 से शुरू होने वाले रोटेशन से छोटा होता है , तो आप कर रहे हैं (पहले एक से शुरू);
  • आप "रोटेशन की शुरुआत प्रत्यय k से शुरू करने की तुलना कर सकते हैं, रोटेशन की तुलना में छोटा होता है प्रत्यय k +1" O (1) में, प्रत्यय की लंबाई और वैकल्पिक रूप से, एक चरित्र की एक दूसरे चरित्र के साथ तुलना करके।

EDIT: "एक वर्ण एक दूसरे वर्ण के साथ" हमेशा ऐसा नहीं हो सकता है, यह एक से अधिक वर्ण हो सकता है, लेकिन कुल मिलाकर, आप संपूर्ण खोज प्रक्रिया के माध्यम से n वर्णों से अधिक की जांच नहीं करते हैं, इसलिए यह O (n) है।

लघु सबूत: आप केवल पात्रों की जांच जब प्रत्यय कश्मीर +1 प्रत्यय से अधिक लंबी है कश्मीर , और आप बंद करो और पाया अपने समाधान यदि प्रत्यय कश्मीर +1 प्रत्यय तुलना में कम है कश्मीर (तो आप को पता प्रत्यय कश्मीर एक आप के लिए मांग की है)। इसलिए आप केवल पात्रों की जांच करते हैं जब आप प्रत्यय के बढ़ते (लंबाई-वार) अनुक्रम में होते हैं। चूँकि आप केवल अतिरिक्त वर्णों की जाँच करते हैं, आप n वर्णों से अधिक की जाँच नहीं कर सकते।

EDIT2: यह एल्गोरिथ्म इस तथ्य पर निर्भर करता है कि "यदि प्रत्यय सरणी में दो पड़ोसी प्रत्यय हैं और पिछला बाद की तुलना में छोटा है, तो पिछला बाद के उपसर्ग है"। अगर यह सच नहीं है, तो क्षमा करें।

EDIT3: नहीं, यह नहीं है। "abaaa" में प्रत्यय तालिका "a", "aa", "aaa", "abaaa", "baaa" है। लेकिन शायद विचार की यह रेखा आखिरकार समाधान की ओर ले जा सकती है, बस कुछ और विवरणों को अधिक परिष्कृत होना चाहिए। प्राथमिक प्रश्न यह है कि क्या किसी तरह कम वर्णों की जांच करके पूर्वोक्त तुलना करना संभव है, इसलिए यह पूरी तरह से ओ (n) है, जो मुझे लगता है कि किसी तरह संभव है। मैं अभी नहीं बता सकता कि कैसे, अब।


0

मुसीबत:

लेक्सोग्राफिक रूप से कम से कम परिपत्र सबस्ट्रिंग ऐसे सभी घुमावों के निम्नतम लेक्सोग्राफिक क्रम वाले स्ट्रिंग के रोटेशन को खोजने की समस्या है। उदाहरण के लिए, "बाबाक़ाक़द" का लेक्सोग्राफिक रूप से न्यूनतम रोटेशन "एकाकदबब" होगा।

समाधान:

जीन पियरे डुवल (1983) द्वारा एओ (एन) समय एल्गोरिथ्म प्रस्तावित किया गया था।

दो सूचकांक को देखते हुए iऔर j, डुवल एल्गोरिथ्म लंबाई की स्ट्रिंग क्षेत्रों तुलना j - iमें प्रारंभिक iऔर j(एक बुलाया "द्वंद्वयुद्ध" )। यदि index + j - iस्ट्रिंग की लंबाई से अधिक है, तो चारों ओर लपेटकर खंड का गठन किया जाता है।

उदाहरण के लिए, s = "बाबाबाबा", i = 5 और j = 7. पर विचार करें। चूंकि j - i = 2, i = 5 से शुरू होने वाला पहला खंड "ab" है। J = 7 पर शुरू होने वाला दूसरा खंड चारों ओर से लपेटकर बनाया गया है, और "ab" भी है। यदि तार लेक्सिकोग्राफ़िक रूप से समान हैं, तो उपरोक्त उदाहरण की तरह, हम विजेता के रूप में i को शुरू करने वाले को चुनते हैं, जो कि i = 5 है।

उपरोक्त प्रक्रिया तब तक दोहराई जाती है जब तक हमारे पास एक भी विजेता न हो। यदि इनपुट स्ट्रिंग विषम लंबाई की है, तो अंतिम वर्ण पहले पुनरावृत्ति में तुलना किए बिना जीतता है।

समय जटिलता:

पहला पुनरावृत्ति लंबाई 1 (एन / 2 तुलना) के प्रत्येक तार की तुलना करता है, दूसरा पुनरावृत्ति लंबाई 2 (एन / 2 तुलना) के एन / 2 तार की तुलना कर सकता है, और इसी तरह, जब तक कि आई-वें पुनरावृत्ति 2 तार की तुलना करता है लंबाई n / 2 (n / 2 तुलना)। चूंकि विजेताओं की संख्या हर बार आधी हो जाती है, पुनरावृत्ति पेड़ की ऊंचाई लॉग (n) है, इस प्रकार हमें एक ओ (एन लॉग (एन)) एल्गोरिदम दे रहा है। छोटे n के लिए, यह लगभग O (n) है।

अंतरिक्ष जटिलता O (n) भी है, क्योंकि पहले पुनरावृत्ति में, हमें n / 2 विजेताओं, दूसरी पुनरावृत्ति n / 4 विजेताओं और इतने पर स्टोर करना होगा। (विकिपीडिया का दावा है कि यह एल्गोरिथ्म निरंतर स्थान का उपयोग करता है, मुझे समझ नहीं आता कि कैसे)।

यहाँ एक स्काला कार्यान्वयन है; अपनी पसंदीदा प्रोग्रामिंग भाषा में बदलने के लिए स्वतंत्र महसूस करें।

def lexicographicallyMinRotation(s: String): String = {
 @tailrec
 def duel(winners: Seq[Int]): String = {
   if (winners.size == 1) s"${s.slice(winners.head, s.length)}${s.take(winners.head)}"
   else {
     val newWinners: Seq[Int] = winners
       .sliding(2, 2)
       .map {
         case Seq(x, y) =>
           val range = y - x
           Seq(x, y)
             .map { i =>
               val segment = if (s.isDefinedAt(i + range - 1)) s.slice(i, i + range)
               else s"${s.slice(i, s.length)}${s.take(s.length - i)}"
               (i, segment)
             }
             .reduce((a, b) => if (a._2 <= b._2) a else b)
             ._1
         case xs => xs.head
       }
       .toSeq
     duel(newWinners)
   }
 }

 duel(s.indices)
}

-1

मुझे O (N²) से बेहतर कुछ नहीं दिखता।

यदि आपके पास N पूर्णांक की सूची है, तो आप O (N) तुलना में सबसे छोटा चुन सकते हैं।

यहां आपके पास आकार N के एन स्ट्रिंग्स की सूची है (निर्माण में उन्हें कुछ भी नहीं खर्च करना है, एक स्ट्रिंग इसके शुरुआती सूचकांक द्वारा पूरी तरह से निर्धारित की जाती है)। आप O (N) तुलना में सबसे छोटा चुन सकते हैं। लेकिन प्रत्येक तुलना ओ (एन) मूल संचालन है। तो जटिलता O (N²) है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.