यदि कोई स्ट्रिंग पूरी तरह से एक ही सबस्ट्रिंग से बना है, तो मैं कैसे जांचूं?


128

मुझे एक फ़ंक्शन बनाना होगा जो एक स्ट्रिंग लेता है, और इसे वापस आना चाहिए trueया falseइस पर आधारित होना चाहिए कि इनपुट में दोहराए गए वर्ण अनुक्रम शामिल हैं या नहीं। दिए गए तार की लंबाई हमेशा से अधिक होती है 1और वर्ण अनुक्रम में कम से कम एक पुनरावृत्ति होना चाहिए।

"aa" // true(entirely contains two strings "a")
"aaa" //true(entirely contains three string "a")
"abcabcabc" //true(entirely containas three strings "abc")

"aba" //false(At least there should be two same substrings and nothing more)
"ababa" //false("ab" exists twice but "a" is extra so false)

मैंने नीचे फ़ंक्शन बनाया है:

function check(str){
  if(!(str.length && str.length - 1)) return false;
  let temp = '';
  for(let i = 0;i<=str.length/2;i++){
    temp += str[i]
    //console.log(str.replace(new RegExp(temp,"g"),''))
    if(!str.replace(new RegExp(temp,"g"),'')) return true;
  }
  return false;
}

console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false

इसकी जाँच करना वास्तविक समस्या का हिस्सा है। मैं इस तरह एक गैर कुशल समाधान बर्दाश्त नहीं कर सकता। सबसे पहले, यह स्ट्रिंग के आधे भाग से गुजर रहा है।

दूसरी समस्या यह है कि यह replace()प्रत्येक लूप में उपयोग कर रहा है जो इसे धीमा कर देता है। क्या प्रदर्शन के संबंध में बेहतर समाधान है?


19
यह लिंक आपके लिए उपयोगी हो सकता है। मुझे हमेशा एल्गोरिथ्म समस्याओं के लिए एक अच्छे स्रोत के रूप में geekforgeeks मिल रहा है - geeksforgeeks.org/…
Leron_says_get_back_Monica

9
क्या आपको बुरा लगता है अगर मैं इसे उधार लेता हूं और इसे प्रोग्रामिंग गोल्फ एक्सचेंज साइट पर एक कोडिंग चुनौती बनाता हूं?
ouflak

7
@ouflak आप ऐसा कर सकते हैं।
माहीर अली

12
आपके जिज्ञासु होने पर, कोडगॉल्फ.स्टैकएक्सचेंज.com
184682

24
@Shidersz इसके लिए तंत्रिका नेटवर्क का उपयोग करना एक मच्छर को मारने के लिए तोप का उपयोग करने जैसा महसूस होता है।
JAD

जवाबों:


186

इस तरह के तार के बारे में एक छोटा सा प्रमेय है।

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

यहाँ, एक रोटेशन का अर्थ है स्ट्रिंग के सामने से कुछ वर्णों को हटाना और उन्हें पीछे की ओर ले जाना। उदाहरण के लिए, स्ट्रिंग helloको इनमें से किसी भी तार को बनाने के लिए घुमाया जा सकता है:

hello (the trivial rotation)
elloh 
llohe 
lohel 
ohell 

यह देखने के लिए कि यह क्यों काम करता है, पहले, मान लें कि एक स्ट्रिंग में एक स्ट्रिंग w की दोहराया प्रतियां शामिल हैं। फिर स्ट्रिंग के सामने से दोहराए गए पैटर्न (डब्ल्यू) की पहली प्रतिलिपि को हटाने और इसे पीछे से निपटने से वही स्ट्रिंग वापस मिल जाएगी। साबित करने के लिए रिवर्स दिशा थोड़ी मुश्किल है, लेकिन विचार यह है कि यदि आप एक स्ट्रिंग को घुमाते हैं और जो आप के साथ शुरू करते हैं वह वापस मिलता है, तो आप उस रोटेशन को एक ही पैटर्न की कई प्रतियों के साथ स्ट्रिंग को टाइल करने के लिए बार-बार लागू कर सकते हैं (यह पैटर्न जा रहा है) स्ट्रिंग आपको रोटेशन करने के लिए अंत में जाने की जरूरत है)।

अब सवाल यह है कि इस बात की जांच कैसे की जाए। उसके लिए, एक और सुंदर प्रमेय है जिसका हम उपयोग कर सकते हैं:

यदि x और y एक ही लंबाई के तार हैं, तो x, y का एक रोटेशन है यदि और केवल यदि x, yy का एक विकल्प है।

एक उदाहरण के रूप में, हम देख सकते हैं कि निम्न lohelके helloरूप में एक रोटेशन है:

hellohello
   ^^^^^

हमारे मामले में, हम जानते हैं कि प्रत्येक स्ट्रिंग x हमेशा xx का एक विकल्प होगा (यह x की प्रत्येक प्रति पर एक बार दो बार दिखाई देगा)। तो मूल रूप से हमें केवल यह जांचने की आवश्यकता है कि क्या हमारा स्ट्रिंग x पहले या आधे रास्ते के चरित्र में मिलान के बिना xx का एक विकल्प है। यहाँ एक लाइनर है कि:

function check(str) {
    return (str + str).indexOf(str, 1) !== str.length;
}

मान लें indexOfकि एक तेज स्ट्रिंग मिलान एल्गोरिथ्म का उपयोग करके लागू किया गया है, यह समय O (n) में चलेगा, जहां n इनपुट स्ट्रिंग की लंबाई है।

उम्मीद है की यह मदद करेगा!


13
बहुत अच्छा! मैंने इसे jsPerf बेंचमार्क पेज पर जोड़ दिया है ।
user42723

10
@ user42723 कूल! ऐसा लगता है कि यह वास्तव में, वास्तव में तेज है।
templatetypedef

5
FYI करें: मुझे उस वाक्य पर विश्वास करने में एक कठिन समय था जब तक कि मैंने शब्द को उलट नहीं दिया: "एक स्ट्रिंग अपने आप में एक स्वैच्छिक रोटेशन है यदि और केवल अगर इसमें एक ही पैटर्न कई बार दोहराया जाता है"। जाओ पता लगाओ।
एक्सल पोडेहल

11
क्या आपके पास उन प्रमेयों का संदर्भ है?
HRK44

4
मुझे लगता है कि पहला बयान " लेम्मा 2.3 : एक्स के समान है और यदि एक्स का एक रोटेशन बराबर है, तो doi.org/10.1016/j.tcs.2008.04.020 पर एक्स दोहराव है" । इन्हें भी देखें: stackoverflow.com/a/2553533/1462295
BurnsBA

67

आप इसे कैप्चरिंग ग्रुप और बैकरेसीफिकेशन द्वारा कर सकते हैं । बस जाँच करें कि यह पहले कैप्चर किए गए मान की पुनरावृत्ति है।

function check(str) {
  return /^(.+)\1+$/.test(str)
}

console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false

उपरोक्त RegExp में:

  1. ^और स्थिति की भविष्यवाणी करने के लिए लंगर शुरू करने और समाप्त करने$ के लिए खड़ा है ।
  2. (.+)किसी भी पैटर्न को पकड़ता है और मूल्य (छोड़कर \n) को पकड़ता है ।
  3. \1पहले पकड़े गए मूल्य का बैकरेन्स है और पकड़े गए मूल्य की \1+पुनरावृत्ति के लिए जाँच करेगा।

रेगेक्स स्पष्टीकरण यहाँ

RegExp डीबगिंग उपयोग के लिए: https://regex101.com/r/pqlAuP/1/debugger

प्रदर्शन: https://jsperf.com/reegx-and-loop/13


2
क्या आप हमें समझा सकते हैं कि यह लाइन क्या कर रही है वापसी />(.+)\1+$/.test(str)
थानवीर शाह

34
इसके अलावा इस समाधान की जटिलता क्या है? मुझे पूरा यकीन नहीं है, लेकिन यह बहुत तेजी से एक ओपी है की तुलना में प्रतीत नहीं होता है।
Leron_says_get_back_Monica

8
@PranavCBalan मैं एल्गोरिदम में अच्छा नहीं हूं, इसलिए मैं टिप्पणी अनुभाग में लिखता हूं। हालाँकि, मेरे पास उल्लेख करने के लिए कई चीजें हैं - ओपी के पास पहले से ही एक काम करने वाला समाधान है, इसलिए वह एक के लिए पूछ रहा है जो उसे बेहतर प्रदर्शन देगा और आपने यह नहीं बताया है कि आपका समाधान कैसे बेहतर होगा। कम तेजी से मतलब नहीं है। इसके अलावा, आपके द्वारा दिए गए लिंक से: If you use normal (TCS:no backreference, concatenation,alternation,Kleene star) regexp and regexp is already compiled then it's O(n).लेकिन जैसा कि आपने लिखा है कि आप बैकरेफरेंस का उपयोग कर रहे हैं तो क्या यह अभी भी O (n) है?
Leron_says_get_back_Monica

5
आप [\s\S]इसके बजाय उपयोग कर सकते हैं .यदि आपको अन्य वर्णों की तरह ही नए वर्णों का मिलान करने की आवश्यकता है। डॉट चरित्र नईलाइन्स पर मेल नहीं खाता है; सभी श्वेत-स्थान और गैर-व्हाट्सएप वर्णों के लिए वैकल्पिक खोज, जिसका अर्थ है कि मैच में newlines शामिल हैं। (ध्यान दें कि यह अधिक सहज ज्ञान युक्त है (.|[\r\n])।) हालांकि, यदि स्ट्रिंग में निश्चित रूप से नई सुर्खियां नहीं हैं, तो सरल .सबसे तेज होगा। ध्यान दें कि यह बहुत आसान होगा अगर डॉट फ्लैग को लागू किया जाता है।
हैप्पीडॉग

2
/^(.+?)\1+$/थोड़ा तेज नहीं है? (12 चरणों बनाम 20 कदम)
ऑनलाइन थॉमस

29

शायद सबसे तेज़ एल्गोरिथम दृष्टिकोण रैखिक समय में एक जेड-फ़ंक्शन का निर्माण कर रहा है :

इस स्ट्रिंग के लिए Z- फ़ंक्शन लंबाई n की एक सरणी है जहां i-th तत्व उस स्थिति की सबसे बड़ी संख्या के बराबर है जो मैं उस स्थिति से शुरू करता हूं जो एस के पहले पात्रों के साथ मेल खाता है।

दूसरे शब्दों में, z [i] s और I पर शुरू होने वाले प्रत्यय के बीच सबसे लंबे सामान्य उपसर्ग की लंबाई है।

संदर्भ के लिए C ++ कार्यान्वयन:

vector<int> z_function(string s) {
    int n = (int) s.length();
    vector<int> z(n);
    for (int i = 1, l = 0, r = 0; i < n; ++i) {
        if (i <= r)
            z[i] = min (r - i + 1, z[i - l]);
        while (i + z[i] < n && s[z[i]] == s[i + z[i]])
            ++z[i];
        if (i + z[i] - 1 > r)
            l = i, r = i + z[i] - 1;
    }
    return z;
}

जावास्क्रिप्ट कार्यान्वयन
जोड़ा अनुकूलन - z- सरणी और जल्दी बाहर निकलने का एक आधा निर्माण

function z_function(s) {
  var n = s.length;
  var z = Array(n).fill(0);
  var i, l, r;
  //for our task we need only a half of z-array
  for (i = 1, l = 0, r = 0; i <= n/2; ++i) {
    if (i <= r)
      z[i] = Math.min(r - i + 1, z[i - l]);
    while (i + z[i] < n && s[z[i]] == s[i + z[i]])
      ++z[i];

      //we can check condition and return here
     if (z[i] + i === n && n % i === 0) return true;
    
    if (i + z[i] - 1 > r)
      l = i, r = i + z[i] - 1;
  }
  return false; 
  //return z.some((zi, i) => (i + zi) === n && n % i === 0);
}
console.log(z_function("abacabacabac"));
console.log(z_function("abcab"));

फिर आपको इंडेक्स की जांच करने की आवश्यकता है iजो एन को विभाजित करते हैं। यदि आप ऐसा पाते हैं i, i+z[i]=nतो स्ट्रिंग sको लंबाई में संकुचित किया जा सकता है iऔर आप वापस लौट सकते हैं true

उदाहरण के लिए, के लिए

string s= 'abacabacabac'  with length n=12`

z- सरणी है

(0, 0, 1, 0, 8, 0, 1, 0, 4, 0, 1, 0)

और हम इसके लिए पा सकते हैं

i=4
i+z[i] = 4 + 8 = 12 = n
and
n % i = 12 % 4 = 0`

इसलिए sलंबाई के प्रतिस्थापन के रूप में प्रतिनिधित्व किया जा सकता है 4 को तीन बार दोहराया गया।


3
return z.some((zi, i) => (i + zi) === n && n % i === 0)
प्रणव सी बालन

2
सलमान ए और प्रणव सी बालन के लिए जावास्क्रिप्ट सामान जोड़ने के लिए धन्यवाद
एमबीओ

1
एक अतिरिक्त पुनरावृत्ति से बचकर वैकल्पिक दृष्टिकोणconst check = (s) => { let n = s.length; let z = Array(n).fill(0); for (let i = 1, l = 0, r = 0; i < n; ++i) { if (i <= r) z[i] = Math.min(r - i + 1, z[i - l]); while (i + z[i] < n && s[z[i]] == s[i + z[i]]) ++z[i]; // check condition here and return if (z[i] + i === n && n % i === 0) return true; if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1; } // or return false return false; }
प्रणव सी। बालन

2
जेड-फंक्शन का उपयोग करना एक अच्छा विचार है, लेकिन यह 'जानकारी -हवाई' है, इसमें बहुत सारी जानकारी होती है जिसका कभी उपयोग नहीं किया जाता है।
एक्सल पोडेहल

@ एक्सल पोडेहल फिर भी, यह ओ (एन) समय में स्ट्रिंग का इलाज करता है (प्रत्येक चार बार अधिकतम दो बार उपयोग किया जाता है)। किसी भी मामले में हमें हर वर्ण की जांच करनी चाहिए, इसलिए कोई सैद्धांतिक रूप से तेज एल्गोरिथ्म नहीं है (जबकि अंतर्निहित तरीकों से बेहतर प्रदर्शन हो सकता है)। इसके अलावा पिछले सम्पादन में मैंने १/२ स्ट्रिंग लंबाई तक सीमित गणना की।
MBo

23

मैंने gnasher729 का उत्तर पढ़ा और इसे लागू किया। विचार यह है कि यदि कोई पुनरावृत्ति है, तो पुनरावृत्ति की एक प्रमुख संख्या भी होनी चाहिए।

function* primeFactors (n) {
    for (var k = 2; k*k <= n; k++) {
        if (n % k == 0) {
            yield k
            do {n /= k} while (n % k == 0)
        }
    }
    if (n > 1) yield n
}

function check (str) {
    var n = str.length
    primeloop:
    for (var p of primeFactors(n)) {
        var l = n/p
        var s = str.substring(0, l)
        for (var j=1; j<p; j++) {
            if (s != str.substring(l*j, l*(j+1))) continue primeloop
        }
        return true
    }
    return false
}

थोड़ा अलग एल्गोरिथ्म यह है:

function check (str) {
    var n = str.length
    for (var p of primeFactors(n)) {
        var l = n/p
        if (str.substring(0, n-l) == str.substring(l)) return true
    }
    return false
}

मैंने jsPerf पृष्ठ अपडेट किया है जिसमें इस पृष्ठ पर उपयोग किए गए एल्गोरिदम हैं।


यह वास्तव में तेजी से लगता है क्योंकि यह अनावश्यक चेक को छोड़ देता है।
प्रणव सी बालन

1
बहुत अच्छा, केवल मुझे लगता है कि मैं यह जाँच करूंगा कि सब-कॉलिंग करने से पहले पहला अक्षर निर्दिष्ट स्थान पर ही है।
बेन वोइग्ट

function*मेरे जैसे पहली बार ठोकर खाने वाले लोगों के लिए, यह एक जनरेटर की घोषणा के लिए है, न कि एक नियमित कार्य। देखें MDN
जुलिएन जगाना

17

मान लें कि स्ट्रिंग S की लंबाई N है और वह सबरिंग s के डुप्लिकेट से बनी है, तो s की लंबाई N से विभाजित होती है। उदाहरण के लिए, यदि S की लंबाई 15 है, तो प्रतिस्थापन की लंबाई 1, 3, या 5 है।

S की (p * q) क से बनी कॉपियों से बना हो। तब S भी (बार-बार q बार) की p प्रतियों से बना होता है। इसलिए हमारे पास दो मामले हैं: यदि N अभाज्य या 1 है, तो S केवल लंबाई के विकल्प की प्रतियों से बना हो सकता है। 1. यदि N संमिश्र है, तो हमें केवल pr / p विभाजन के लिए लंबाई N / p के सबस्ट्रिंग की जाँच करने की आवश्यकता है। एस की लंबाई।

इसलिए एन = एस की लंबाई निर्धारित करें, फिर ओ (स्क्वेयर (एन)) में अपने सभी प्रमुख कारकों को ढूंढें। यदि केवल एक कारक N है, तो जांचें कि क्या S एक ही स्ट्रिंग बार-बार दोहराया गया N है, अन्यथा प्रत्येक अभाज्य कारक p के लिए, यदि S में पहले N / p वर्णों के पुनरावर्तन होते हैं।


मैंने अन्य समाधानों की जाँच नहीं की है, लेकिन यह बहुत तेज़ लगता है। आप "यदि केवल एक कारक एन है, तो जांचें ..., अन्यथा" सादगी के लिए भाग छोड़ सकते हैं, क्योंकि यह कोई विशेष मामला नहीं है। एक जावास्क्रिप्ट कार्यान्वयन को देखना अच्छा होगा जो अन्य कार्यान्वयनों के बगल में jsPerf में चलाया जा सकता है।
user42723

1
मैंने अब इसे अपने उत्तर
user42723

10

मुझे लगता है कि एक पुनरावर्ती कार्य बहुत तेज हो सकता है। पहला अवलोकन यह है कि कुल स्ट्रिंग के रूप में अधिकतम दोहराया पैटर्न की लंबाई आधी है। और हम सभी संभावित दोहराया पैटर्न की लंबाई का परीक्षण कर सकते हैं: 1, 2, 3, ..., str.length / 2

यदि इस पैटर्न को स्ट्रेट में दोहराया जाता है, तो पुनरावर्ती फ़ंक्शन रीपिटिंग (पी, स्ट्र) का परीक्षण करता है।

यदि पैटर्न से अधिक लंबा है, तो पुनरावृत्ति के लिए पुनरावृत्ति के साथ-साथ str के शेष भाग के पहले भाग (p के समान लंबाई) की आवश्यकता होती है। तो str प्रभावी रूप से लंबाई p.length के टुकड़ों में टूट जाता है।

यदि परीक्षण किया गया पैटर्न और str समान आकार के हैं, तो पुनरावृत्ति यहाँ समाप्त होती है, सफलतापूर्वक।

यदि लंबाई अलग है ("aba" और पैटर्न "ab" के लिए होता है) या यदि टुकड़े अलग-अलग हैं, तो पुनरावर्तन का प्रचार करते हुए, झूठे को वापस कर दिया जाता है।

function check(str)
{
  if( str.length==1 ) return true; // trivial case
  for( var i=1;i<=str.length/2;i++ ) { // biggest possible repeated pattern has length/2 characters

    if( str.length%i!=0 ) continue; // pattern of size i doesn't fit
    
    var p = str.substring(0, i);
    if( isRepeating(p,str) ) return true;
  }
  return false;
}


function isRepeating(p, str)
{
  if( str.length>p.length ) { // maybe more than 2 occurences

    var left = str.substring(0,p.length);
    var right = str.substring(p.length, str.length);
    return left===p && isRepeating(p,right);
  }
  return str===p; 
}

console.log(check('aa')) //true
console.log(check('aaa')) //true 
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false

प्रदर्शन: https://jsperf.com/reegx-and-loop/13


1
क्या if( str===p.repeat(str.length/i) ) return true;पुनरावर्ती फ़ंक्शन का उपयोग करने के बजाय जांच करना तेज़ होगा ?
क्रोनोसाइडल

1
Jsperf परीक्षणों में कंसोल.लॉग्स न डालें, ग्लोबल्स सेक्शन के अंदर फ़ंक्शंस तैयार करें, ग्लोबल्स सेक्शन में टेस्ट स्ट्रिंग्स भी तैयार करें (क्षमा करें, jsperf संपादित नहीं कर सकते)
सलमान A

@ सलमान - अच्छी बात है। मैंने सिर्फ अपने पूर्ववर्ती (प्रणव C) से jsperf को संशोधित किया, पहली बार मैंने jsperf, कूल टूल का उपयोग किया।
एक्सल पोडेहल

@ सलमान: अपडेटेड: jsperf.com/regex-and-loop/1 ... जानकारी के लिए धन्यवाद ... यहां तक ​​कि मैं इससे परिचित नहीं हूं (जेस्परफ) ... जानकारी के लिए धन्यवाद
प्रणव सी बालन

हाय सलमान, jsperf.com/reegx-and-loop/10 के लिए बहुत बहुत धन्यवाद - हाँ, यह नया पूर्ण परीक्षण बहुत मायने रखता है। फ़ंक्शन का सेटअप तैयारी कोड में जाना चाहिए।
एक्सल पोडेहल

7

इसे पायथन में लिखा। मुझे पता है कि यह मंच नहीं है, लेकिन इसमें 30 मिनट का समय लगा। पीएस => पायथन

def checkString(string):
    gap = 1 
    index= 0
    while index < len(string)/2:
        value  = [string[i:i+gap] for i in range(0,len(string),gap) ]

        x = [string[:gap]==eachVal for eachVal in value]

        if all(x):
            print("THEY ARE  EQUAL")
            break 

        gap = gap+1
        index= index+1 

checkString("aaeaaeaaeaae")

6

मेरा दृष्टिकोण gnasher729 के समान है, इसमें यह मुख्य फोकस के रूप में सबस्ट्रिंग की संभावित लंबाई का उपयोग करता है, लेकिन यह कम गणित-y और प्रक्रिया गहन है:

एल: मूल स्ट्रिंग की लंबाई

एस: वैध उप-तारों की संभावित लंबाई

लूप S से (पूर्णांक भाग) L / 2 से 1. यदि L / S एक पूर्णांक है, तो मूल स्ट्रिंग के L / S बार दोहराए जाने वाले मुट्ठी के S अक्षर के विरुद्ध अपने मूल स्ट्रिंग की जाँच करें।

एल / 2 से पीछे की ओर और 1 के बाद से नहीं होने का कारण सबसे बड़ा संभव विकल्प प्राप्त करना है। यदि आप 1 से एल / 2 तक सबसे छोटा संभव विकल्प लूप चाहते हैं। उदाहरण: "अबाबैब" में संभव एबिंग के रूप में "एब" और "एबब" दोनों होते हैं। यदि आप केवल सही / गलत परिणाम की परवाह करते हैं तो दोनों में से कौन सा तेज होगा, यह इस पर लागू होने वाले स्ट्रिंग्स / सबस्ट्रिंग के प्रकार पर निर्भर करता है।


5

यदि सूची कम से कम एक बार दोहराई जाती है, तो निम्न गणित कोड लगभग पता लगाता है। यदि स्ट्रिंग को कम से कम एक बार दोहराया जाता है, तो यह सच हो जाता है, लेकिन अगर स्ट्रिंग बार-बार तार का एक रैखिक संयोजन है, तो यह भी सच हो सकता है।

IsRepeatedQ[list_] := Module[{n = Length@list},
   Round@N@Sum[list[[i]] Exp[2 Pi I i/n], {i, n}] == 0
];

यह कोड "पूर्ण-लंबाई" योगदान के लिए दिखता है, जिसे एक दोहराए जाने वाले स्ट्रिंग में शून्य होना चाहिए, लेकिन स्ट्रिंग accbbdको भी दोहराया जाता है, क्योंकि यह दो दोहराया स्ट्रिंग abababऔर का योग है 012012

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


4

यहां मूल विचार किसी भी संभावित विकल्प की जांच करना है, जिसकी लंबाई 1 से शुरू होती है और मूल स्ट्रिंग की लंबाई के आधे भाग पर रुकती है। हम केवल मूल स्ट्रिंग की लंबाई को विभाजित करने वाले स्ट्रिंग को ही देखते हैं (यानी str.length% substring.length = 0)।

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

जब हम जांच करने के लिए संभावित सबस्ट्रिंग से बाहर निकलते हैं तो हम झूठे हो जाते हैं।

function check(str) {
  const len = str.length;
  for (let subl = 1; subl <= len/2; ++subl) {
    if ((len % subl != 0) || str[0] != str[subl])
      continue;
    
    let i = 1;
    for (; i < subl; ++i)
    {
      let j = 0;
      for (; j < len; j += subl)
        if (str[i] != str[j + i])
          break;
      if (j != len)
        break;
    }
    
    if (i == subl)
      return true;
  }
  return false;
}

console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false


-1

मैं जावास्क्रिप्ट से परिचित नहीं हूं, इसलिए मुझे नहीं पता कि यह कितनी तेजी से होने वाला है, लेकिन यहां केवल बिल्डिंस का उपयोग करके एक रैखिक समय समाधान (उचित बिलिन कार्यान्वयन को संभालने) है। मैं pseudocode में एल्गोरिथ्म का वर्णन करूँगा।

function check(str) {
    t = str + str;
    find all overlapping occurrences of str in t;
    for each occurrence at position i
        if (i > 0 && i < str.length && str.length % i == 0)
            return true;  // str is a repetition of its first i characters
    return false;
}

विचार एमबीओ के उत्तर के समान है। प्रत्येक के लिए iजो लंबाई को विभाजित करता है, strअपने पहले iपात्रों की पुनरावृत्ति है यदि और केवल यदि यह iवर्णों के लिए स्थानांतरण के बाद भी ऐसा ही रहता है ।

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


ओपी जानना चाहता है कि पुनरावृत्ति मौजूद है या नहीं । आपके कार्य की दूसरी पंक्ति (निकाय) आपके दोहराव की संख्या को गिनाती है - यह वह बिट है जिसे समझाने की आवश्यकता है। उदाहरण के लिए "abcabcabc" में "abc" की 3 पुनरावृत्तियाँ हैं, लेकिन आपकी दूसरी पंक्ति कैसे काम करती है, क्या इसमें कोई दोहराव था?
लॉरेंस

@ लॉरेंस मैं आपके सवाल को नहीं समझता। इस एल्गोरिथ्म विचार है कि स्ट्रिंग तभी इसकी लंबाई के कुछ भाजक के लिए करता है, तो अपने-स्ट्रिंग की पुनरावृत्ति है पर आधारित है i, s[0:n-i] == s[i:n], या समतुल्य s == s[i:n] + s[0:i]। दूसरी पंक्ति को काम करने की आवश्यकता क्यों है, क्या इसमें कोई दोहराव था?
infmagic2047

अगर मैं आपके एल्गोरिथ्म को समझता हूं तो मुझे देखने दें। सबसे पहले, आप strखुद को बनाने के लिए अपील करते हैं t, फिर अंदर tखोजने की कोशिश करने के लिए स्कैन करते हैं । ठीक है, यह काम कर सकता है (मैंने अपना पद छोड़ दिया है)। हालांकि यह strlen (str) में रैखिक नहीं है। कहते हैं प्रत्येक स्थिति में तब लंबाई एल की है पी = 0,1,2, ..., देखना हो str [0..L -1] == टी [p..p + एल -1] हे लेता है (एल ) समय। जैसे ही आप p के मानों से गुजरते हैं, आपको O (L) चेक करने की आवश्यकता होती है, इसलिए यह O (L ^ 2) है। strtstr
लॉरेंस

-10

सरल विचारों में से एक स्ट्रिंग को "" के प्रतिस्थापन के साथ बदलना है और यदि कोई पाठ मौजूद है तो यह गलत है, अन्यथा यह सत्य है।

'ababababa'.replace(/ab/gi,'')
"a" // return false
'abababab'.replace(/ab/gi,'')
 ""// return true


हाँ, abc या यूनिकॉर्न के लिए उपयोगकर्ता / abc / या / unicorn / के साथ जाँच नहीं करेगा, क्षमा करें यदि मुझे आपका संदर्भ याद आ रहा है
विनोद कुमार G

3
प्रश्न स्पष्ट हो सकता है, लेकिन यह क्या मांग रहा है यह तय करने का एक तरीका है कि क्या स्ट्रिंग पूरी तरह से 2 या किसी अन्य स्ट्रिंग के दोहराव से बना है। यह एक विशिष्ट विकल्प के लिए नहीं खोज रहा है।
हैप्पीडॉग

2
मैंने प्रश्न के लिए कुछ स्पष्टीकरण जोड़ा है, जो अब इसे स्पष्ट करना चाहिए।
हैप्पीडॉग

@Vinod यदि आप पहले से ही regex का उपयोग करने जा रहे हैं, तो आपको अपने मैच का उपयोग करना चाहिए और परीक्षण का उपयोग करना चाहिए। केवल कुछ स्थिति को मान्य करने के लिए स्ट्रिंग को संशोधित करने का कोई कारण नहीं।
मैरी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.