साक्षात्कार प्रश्न: जांचें कि क्या एक स्ट्रिंग अन्य स्ट्रिंग का रोटेशन है [बंद]


235

मेरा एक दोस्त सॉफ्टवेयर डेवलपर की स्थिति के लिए साक्षात्कार में आज निम्नलिखित प्रश्न पूछा गया था:

दो स्ट्रिंग को देखते हुए s1और s2आप अगर कैसे की जाँच करेगा s1एक है घुमाया के संस्करण s2?

उदाहरण:

यदि s1 = "stackoverflow"निम्नलिखित इसके कुछ घुमाए गए संस्करण हैं:

"tackoverflows"
"ackoverflowst"
"overflowstack"

जहां के रूप में "stackoverflwo"है नहीं घुमाए गए संस्करण।

उन्होंने जो उत्तर दिया वह था:

ले लो s2और सबसे लंबे समय तक उपसर्ग खोजें जो एक उप स्ट्रिंग है s1, जो आपको रोटेशन की बात देगा। एक बार जब आप s2उस बिंदु को पा लेते हैं , तो पाने के लिए उस बिंदु पर ब्रेक लें s2aऔर s2bफिर, बस जांचें कि क्याconcatenate(s2a,s2b) == s1

यह मेरे और मेरे दोस्त के लिए एक अच्छा समाधान की तरह लग रहा है। लेकिन साक्षात्कारकर्ता ने अन्यथा सोचा। उन्होंने एक सरल समाधान के लिए कहा। कृपया मुझे यह बताकर मदद करें कि आप यह कैसे करेंगे Java/C/C++?

अग्रिम में धन्यवाद।


4
आपको यह जांचने की ज़रूरत नहीं है कि क्या समवर्ती (s2a, s2b) == s1, क्योंकि आप जानते हैं कि s2a s1 की शुरुआत के बराबर है। आप बस जांच सकते हैं कि क्या s2b == रोटेशन से एफ़ 1 से एस 1 का विकल्प समाप्त हो रहा है।
जेसन हॉल

33
यह सवाल और शीर्ष उत्तर इतने सारे उत्थान कैसे मिले !?
डेविड जॉनस्टोन

9
@ डेविड: क्योंकि यह दिलचस्प है।
कैम

6
मैं कहूंगा, बहुत दिलचस्प और एक सुरुचिपूर्ण, सरल जवाब।
गुरू

7
@ डेविड: क्योंकि यह एक ऐसा प्रश्न है जो यहाँ से पहले नहीं पूछा गया है और जिसे सभी लोग समझते हैं (यदि कोई प्रश्न / उत्तर को नहीं समझता है, तो आमतौर पर यह सुनिश्चित करने के लिए होगा कि कोई इसे अपवित्र न करे; एक बहुत ही सरल प्रश्न का एक व्यापक दर्शक है) और भी क्योंकि यह जावा और सी। दोनों के साथ टैग किया गया है। इसकी गिनती :)
बाल्सक

जवाबों:


687

पहले सुनिश्चित करें s1और s2एक ही लंबाई के हैं। तो फिर यह देखने हेतु जांचने s2की सबस्ट्रिंग है s1साथ concatenated s1:

algorithm checkRotation(string s1, string s2) 
  if( len(s1) != len(s2))
    return false
  if( substring(s2,concat(s1,s1))
    return true
  return false
end

जावा में:

boolean isRotation(String s1,String s2) {
    return (s1.length() == s2.length()) && ((s1+s1).indexOf(s2) != -1);
}

49
मुझे इसकी लालित्य पसंद है, लेकिन मुझे जाँचने के लिए कुछ समय के लिए सोचना पड़ा कि कोई झूठी सकारात्मकता नहीं है। (मुझे नहीं लगता कि वहाँ हैं।)
जॉन स्कीट

6
आप (s1+s1).contains(s2)जावा में भी उपयोग कर सकते हैं ।
पॉलीजेन लुब्रीकेंट

4
वैसे भी मैं एक साक्षात्कार प्रश्न के रूप में इस पर थोड़ी सी आपत्ति करूंगा। यह एक "अहा!" घटक, मुझे लगता है। अधिकांश प्रोग्रामर (मुझे शामिल किया गया) बस ब्रूट फोर्स का उपयोग करेंगे, जो वैसे भी अनुचित नहीं है, और यह साक्षात्कारकर्ता के लिए पर्याप्त "चतुर" नहीं लग सकता है।
डेनियल डारनास

5
@Jon पर ध्यान लगाओ s1+s1। स्पष्ट रूप से, आकार के साथ इसके सभी पदार्थ निर्माण के s1.lengthघूर्णन हैं s1। इसलिए, आकार के किसी भी तार का s1.lengthएक विकल्प है जो s1+s1एक घुमाव होना चाहिए s1
डैनियल सी। सोबरल

6
@unicornaddict - इस समाधान के बारे में क्या शानदार है यह स्पष्ट है कि एक बार जब आप इसे इंगित करते हैं, तो मैं इसके बारे में न सोचने के लिए खुद से नफरत करता हूं!
जेम्स बी

101

निश्चित रूप से एक बेहतर जवाब होगा, "ठीक है, मैं स्टैकओवरफ़्लो समुदाय से पूछूंगा और शायद 5 मिनट के भीतर कम से कम 4 वास्तव में अच्छे उत्तर होंगे"। दिमाग अच्छे और सभी हैं, लेकिन मैं किसी ऐसे व्यक्ति पर एक उच्च मूल्य रखता हूं जो जानता है कि समाधान पाने के लिए दूसरों के साथ कैसे काम करना है।


14
सरासर गाल के लिए +1। मेरा दिन बना दिया :-)
प्लैटिनम एज़ुर

5
यदि वे असहमत थे, तो आप उन्हें इस प्रश्न से जोड़ सकते हैं।
कैम

51
एक साक्षात्कार के दौरान अपने सेलफोन को मारना असभ्य माना जा सकता है और अंत में वे जॉन स्कीट को काम पर रखना चाहेंगे।
तंस्टनर

2
यह वास्तव में संभवतः वैसा ही है जैसा मैंने कहा होगा
क्रिस डुट्रो

6
मुझे नहीं लगता कि वे जॉन स्कीट को बर्दाश्त कर पाएंगे।
SolutionYogi

49

एक और अजगर उदाहरण (उत्तर के आधार पर):

def isrotation(s1,s2):
     return len(s1)==len(s2) and s1 in 2*s2

1
दिलचस्प बात यह है कि मैंने भी नकल s2करने के बारे में सोचा था s1... फिर एहसास हुआ कि रिश्ता वैसे भी सममित था।
Matthieu M.

1
यदि स्ट्रिंग लंबी हो सकती है, तो यहां एक पायथन संस्करण है जो ओ (एन) रनिंग टाइम पाने के लिए बोयर-मूर का उपयोग करता है: डीफ़्रोटेशन (s1, s2): रिटर्न लेन (s1) == लेन (s2) और re.compile (पुनः) .escape (s1))। खोज (2 * s2) कोई नहीं है
डंकन

2
@ डंकन: inऑपरेटर ओ (एन) एल्गोरिथ्म का उपयोग नहीं करता है?
केन ब्लूम

1
@ डंकन: अजगर स्ट्रिंग विधियाँ एक अनुकूलित बॉयर-मूर-हॉर्सपूल का उपयोग करती हैं। मुझे आश्चर्य है कि अगर जावा में समान अनुकूलन हैं।
थॉमस अहले

1
@ थोमस ने जो इशारा किया उसके लिए धन्यवाद। मैंने सोचा था कि केवल नियमित अभिव्यक्तियों में बॉयर-मूर का उपयोग किया गया था लेकिन मुझे लगता है कि मैं गलत था। पायथन 2.4 और पहले के लिए मेरा उत्तर सही था लेकिन चूंकि पायथन 2.5 s1 in s2अनुकूलित है। एल्गोरिथ्म के वर्णन के लिए effbot.org/zone/stringlib.htm देखें । Google इंगित करता है कि जावा में तेज स्ट्रिंग खोज नहीं है ( उदाहरण के लिए johannburkard.de/software/stringsearch देखें ) हालांकि मुझे संदेह है कि अगर वे इसे बदल देते हैं तो यह कुछ भी तोड़ देगा।
डंकन

32

जैसा कि दूसरों ने द्विघात सबसे खराब समय जटिलता समाधान प्रस्तुत किया है, मैं एक रैखिक एक ( केएमपी एल्गोरिदम के आधार पर ) जोड़ूंगा :

bool is_rotation(const string& str1, const string& str2)
{
  if(str1.size()!=str2.size())
    return false;

  vector<size_t> prefixes(str1.size(), 0);
  for(size_t i=1, j=0; i<str1.size(); i++) {
    while(j>0 && str1[i]!=str1[j])
      j=prefixes[j-1];
    if(str1[i]==str1[j]) j++;
    prefixes[i]=j;
  }

  size_t i=0, j=0;
  for(; i<str2.size(); i++) {
    while(j>0 && str2[i]!=str1[j])
      j=prefixes[j-1];
    if(str2[i]==str1[j]) j++;
  }
  for(i=0; i<str2.size(); i++) {
    if(j>=str1.size()) return true;
    while(j>0 && str2[i]!=str1[j])
      j=prefixes[j-1];
    if(str2[i]==str1[j]) j++;
  }

  return false;
}

काम करने का उदाहरण


5
Ideone.com के लिए +1 - यह बहुत दिलचस्प लगता है!
मार्टिन विसेटीका

25

संपादित करें: यदि आप इसे स्पॉट करते हैं, तो स्वीकृत उत्तर स्पष्ट रूप से अधिक सुरुचिपूर्ण और कुशल है। मैंने यह उत्तर छोड़ दिया कि मैं क्या करूँगा अगर मैंने मूल स्ट्रिंग को दोगुना करने के बारे में नहीं सोचा था।


मैं बस इसे बल देना चाहता था। पहले लंबाई की जांच करें, और फिर हर संभव रोटेशन की कोशिश करें। यदि उनमें से कोई भी काम नहीं करता है, तो झूठे लौटें - यदि उनमें से कोई भी करता है, तो तुरंत सच लौटें।

कोई विशेष करने की आवश्यकता नहीं है - बस पॉइंटर्स (C) या इंडेक्स (जावा) का उपयोग करें और दोनों को साथ में चलें, प्रत्येक स्ट्रिंग में एक - एक स्ट्रिंग की शुरुआत में और वर्तमान उम्मीदवार रोटेशन दूसरी स्ट्रिंग में ऑफसेट करें, और जहां आवश्यक हो वहां रैप करें। । स्ट्रिंग में प्रत्येक बिंदु पर वर्ण समानता के लिए जाँच करें। यदि आप पहले तार के अंत तक पहुँचते हैं, तो आप कर रहे हैं।

संभवत: यह कम से कम जावा में कम से कम कुशल है - हालांकि यह आसान है।


8
+1 - हमें किसी ऐसे सुरुचिपूर्ण समाधान की आवश्यकता नहीं है जो 3+ बार सबसे कुशल समाधान में चले। यह C है ... माइक्रो-ऑप्टिमाइजेशन डी रिग्युअर है
स्टीफन सी

8
साक्षात्कारकर्ता: लोट्टा बात करते हैं, लेकिन मुझे यकीन है कि यह आदमी कोड नहीं कर सकता।
हम्फ्रे बोगार्ट

8
@ ब्यू: यदि कोई यह सोचना चाहता है, तो कोड के लिए मुझसे पूछने का स्वागत करते हैं। अगर कोई मुझसे सिर्फ यह पूछता है कि "मैं कुछ कैसे करूंगा" तो मैं आमतौर पर कोड को छलांग लगाने के बजाय एल्गोरिथ्म का वर्णन करता हूं।
जॉन स्कीट

3
@ जों - मैंने ब्यू की टिप्पणी को मजाक के रूप में पढ़ा
ऑक्सबो_लक्स

37
@ यह एक मजाक था! साक्षात्कारकर्ता जॉन स्कीट का साक्षात्कार नहीं करता है, जॉन स्कीट उसका साक्षात्कार लेता है।
हम्फ्रे बोगार्ट

17

यहाँ केवल मज़े के लिए regex का उपयोग किया जा रहा है:

boolean isRotation(String s1, String s2) {
   return (s1.length() == s2.length()) && (s1 + s2).matches("(.*)(.*)\\2\\1");
}

आप इसे थोड़ा सरल बना सकते हैं यदि आप किसी विशेष सीमांकक चरित्र का उपयोग कर सकते हैं जिसकी गारंटी या तो तार में नहीं है।

boolean isRotation(String s1, String s2) {
   // neither string can contain "="
   return (s1 + "=" + s2).matches("(.*)(.*)=\\2\\1");
}

आप इसके बजाय परिमित पुनरावृत्ति के साथ भी देख सकते हैं:

boolean isRotation(String s1, String s2) {
   return (s1 + s2).matches(
      String.format("(.*)(.*)(?<=^.{%d})\\2\\1", s1.length())
   );
}

6
रेगेक्स मास्टर होने के लिए +1।
क्रिस थॉर्नटन

-1 "रेगेक्स" और "फन" शब्दों को एक ही स्टेटमेंट में डालने के लिए, "मस्ती" को "नहीं" (केवल मजाक में, मैंने वोट नहीं दिया) को संशोधित किए बिना
बाइनरी वॉरियर

-3 यह आरोप लगाने के लिए कि रेगीज़ मज़ेदार नहीं हैं।
23

क्या कोई भी निकाय समझा सकता है कि यह रेगेक्स "(। *) (। *) = \\ 2 \\ 1" ने कैसे काम किया!
माविया

10

वाह, वाह ... हर कोई एक O(n^2)जवाब से इतना रोमांचित क्यों है ? मैं सकारात्मक हूं कि हम यहां बेहतर कर सकते हैं। ऊपर दिए गए उत्तर O(n)में O(n)लूप में एक ऑपरेशन (सबस्ट्रिंग / इंडेक्सऑफ कॉल) शामिल है। एक अधिक कुशल खोज एल्गोरिदम के साथ भी; कहते हैं कि Boyer-Mooreया KMP, बुरी से बुरी हालत अब भी है O(n^2)डुप्लिकेट के साथ।

एक O(n)यादृच्छिक जवाब सीधा है; एक हैश (जैसे राबिन फ़िंगरप्रिंट) लें जो O(1)स्लाइडिंग विंडो का समर्थन करता है ; हैश स्ट्रिंग 1, फिर हैश स्ट्रिंग 2, और स्ट्रिंग के चारों ओर हैश 1 के लिए विंडो को स्थानांतरित करने के लिए आगे बढ़ें और देखें कि क्या हैश टकराता है।

अगर हम सबसे बुरे मामले की कल्पना करते हैं जैसे "डीएनए के दो किस्में स्कैन करना", तो टकराव की संभावना बढ़ जाती है, और यह संभवतः कुछ O(n^(1+e))या कुछ और (बस यहां अनुमान लगाने) के लिए पतित हो जाता है ।

अंत में, एक निर्धारक O(nlogn)समाधान है जिसमें एक बहुत बड़ा स्थिरांक है। मूल रूप से, विचार दो तारों का एक दृढ़ संकल्प लेने का है। सजा का अधिकतम मूल्य रोटेशन अंतर होगा (यदि वे घुमाए गए हैं); एक O(n)जाँच की पुष्टि करता है। अच्छी बात यह है कि यदि दो समान अधिकतम मूल्य हैं, तो वे दोनों भी वैध समाधान हैं। आप दो एफएफटी और एक डॉट उत्पाद, और एक आईएफएफटी के साथ कनविक्शन कर सकते हैं nlogn + nlogn + n + nlogn + n == O(nlogn)

चूंकि आप शून्य के साथ पैड नहीं कर सकते हैं, और आप गारंटी नहीं दे सकते कि तार 2 ^ n लंबाई के हैं, एफएफटी तेजी से नहीं होंगे; वे धीमे वाले होंगे, फिर भी O(nlogn)सीटी एल्गोरिथम की तुलना में बहुत अधिक स्थिर रहेंगे ।

उस सभी ने कहा, मैं बिल्कुल ठीक हूं, 100% सकारात्मक है कि यहां एक नियतात्मक O(n)समाधान है, लेकिन अगर मैं इसे पा सकता हूं तो हिम्मत की।


केएमपी पर ही-स्ट्रिंग के साथ (या तो शारीरिक रूप से या वस्तुतः ए के साथ %stringsize ) के रैखिक समय होने की गारंटी है।
क्रैगन जेवियर सीटेकर

राबिन-कार्प के लिए +1। KMP के विपरीत, यह निरंतर स्थान का उपयोग करता है, और इसे लागू करने के लिए सरल है। (यह पहला ऐसा उत्तर है जिसके बारे में मैंने सेकंड में सोचा था, जिससे 'सही' उत्तर को देखना मुश्किल हो जाता है, क्योंकि यह किसी का अधिकार है और यह मीठा है।) आपका कनविक्शन आइडिया मुझे शोर के एल्गोरिथ्म की याद दिलाता है - मुझे आश्चर्य है कि क्या कोई सबलाइन है क्वांटम समाधान - लेकिन यह अब मूर्खतापूर्ण हो रहा है, है ना?
डेरियस बेकन

1
आरके एक निर्धारक ओ (एन) समाधान नहीं देता है, और केएमपी अंतरिक्ष में ओ (एन) है जो अवांछनीय हो सकता है। दो तरह से देखो या एसएमओए प्रतिस्थापन खोज जो समय में ओ (एन) और अंतरिक्ष में ओ (1) दोनों हैं। वैसे, glibc स्ट्रैस टू वे का उपयोग करता है, लेकिन अगर आप वास्तव में स्ट्रैटन का उपयोग करते हैं तो इसे% len का उपयोग करने के लिए विरोध के रूप में आप अंतरिक्ष में O (n) पर वापस आ रहे हैं। :-)
आर .. गिटहब स्टॉप हेल्पिंग आईसीई

8

मुट्ठी, सुनिश्चित करें कि 2 तारों की लंबाई समान है। फिर सी में, आप एक साधारण सूचक पुनरावृत्ति के साथ ऐसा कर सकते हैं।


int is_rotation(char* s1, char* s2)
{
  char *tmp1;
  char *tmp2;
  char *ref2;

  assert(s1 && s2);
  if ((s1 == s2) || (strcmp(s1, s2) == 0))
    return (1);
  if (strlen(s1) != strlen(s2))
    return (0);

  while (*s2)
    {
      tmp1 = s1;
      if ((ref2 = strchr(s2, *s1)) == NULL)
        return (0);
      tmp2 = ref2;
      while (*tmp1 && (*tmp1 == *tmp2))
        {
          ++tmp1;
          ++tmp2;
          if (*tmp2 == '\0')
            tmp2 = s2;
        }
      if (*tmp1 == '\0')
        return (1);
      else
        ++s2;
    }
  return (0);
}

19
जब आप C में कर सकते हैं तो आह, C. आधे समय और कोड में कुछ क्यों करें!
हम्फ्री बोगार्ट

11
+1 यह बहुत अच्छी तरह से लिखा गया है। सी। और निष्पक्ष होने के लिए, प्रश्न को 'सी' टैग किया गया है।
निक मूर

5
इस कोड में आपने स्ट्रिंग्स को कम से कम 2 चला दिया है यदि 3 बार नहीं (स्ट्रलेन और स्ट्रैम्प में)। आप अपने आप को इस चेक को बचा सकते हैं और आप उस तर्क को अपने पाश में रख सकते हैं। जैसा कि आप लूपिंग कर रहे हैं, यदि एक स्ट्रिंग कैरेक्टर काउंट दूसरे से अलग है, तो लूप से बाहर निकलें। आपको लंबाई पता चल जाएगी, जैसा कि आप जानते हैं कि आप शुरू करते हैं और आपको पता है कि आपने शून्य टर्मिनेटर को कब मारा है।
नास्को

12
@ ब्यू मार्टिनेज - क्योंकि कभी-कभी निष्पादन समय विकास के समय से अधिक महत्वपूर्ण होता है :-)
फकहलर

2
@ फकहलर - बात यह है कि यह अच्छी तरह से धीमी हो सकती है। अन्य भाषाओं में इंडेक्स फ़ंक्शंस में आमतौर पर बॉयर-मूर, राबिन-कार्प या नूथ-मॉरिस-प्रैट जैसे तेज़ स्ट्रिंग खोज एल्गोरिथ्म का उपयोग किया जाता है। यह बहुत भोला है बस सी में सब कुछ को मजबूत करें, और इसे तेजी से मान लें।
थॉमस अहले

8

यहाँ एक O(n)और जगह में है। यह <स्ट्रिंग्स के तत्वों के लिए ऑपरेटर का उपयोग करता है । यह निश्चित रूप से मेरा नहीं है। मैंने इसे यहाँ से ले लिया (साइट पॉलिश में है। मैंने अतीत में एक बार इस पर ठोकर खाई थी और मुझे अब अंग्रेजी में ऐसा कुछ नहीं मिल रहा है, इसलिए मैं दिखाता हूं कि मेरे पास क्या है :))।

bool equiv_cyc(const string &u, const string &v)
{
    int n = u.length(), i = -1, j = -1, k;
    if (n != v.length()) return false;

    while( i<n-1 && j<n-1 )
    {
        k = 1;
        while(k<=n && u[(i+k)%n]==v[(j+k)%n]) k++;
        if (k>n) return true;
        if (u[(i+k)%n] > v[(j+k)%n]) i += k; else j += k;
    }
    return false;
}

+1 ... हे (एन) बस है sooooo भी बहुत कुछ एक से गहरा कंप्यूटर अनुप्रयोग-विज्ञान किसी भी गैर से दृष्टि हे (एन) समाधान :)
SyntaxT3rr0r

4
एक समाधान के लिए +1 जो कोड-आकार में समय और निकट-इष्टतम है (बाइनरी और एलओसी दोनों) में इष्टतम है। स्पष्टीकरण के साथ यह उत्तर और भी बेहतर होगा।
आर .. गिटहब स्टॉप हेल्पिंग ICE

पूरी तरह से चकरा देने वाला। हमें एक स्पष्टीकरण की आवश्यकता है!
j_random_hacker

7

मुझे लगता है कि ऐसा करने में बेहतर है Java:

boolean isRotation(String s1,String s2) {
    return (s1.length() == s2.length()) && (s1+s1).contains(s2);
}

पर्ल में मैं करूँगा:

sub isRotation {
 my($string1,$string2) = @_;
 return length($string1) == length($string2) && ($string1.$string1)=~/$string2/;
}

या regex के बजाय इंडेक्स फ़ंक्शन का उपयोग करना बेहतर है :

sub isRotation {
 my($string1,$string2) = @_;
 return length($string1) == length($string2) && index($string2,$string1.$string1) != -1;
}

1
तुम भूल \Qगए /\Q$string2/
क्रैगन जेवियर सीटेकर

3
\Qमें किसी विशेष वर्ण को उद्धृत करता है $string2। इसके बिना, .किसी भी 1-वर्ण स्ट्रिंग का रोटेशन माना जाएगा।
जैकबबिट

6

यकीन नहीं है कि यह सबसे कुशल तरीका है, लेकिन यह अपेक्षाकृत दिलचस्प हो सकता है : बर्स-व्हीलर परिवर्तन । WP लेख के अनुसार, इनपुट के सभी घुमाव समान आउटपुट देते हैं। संपीड़न जैसे अनुप्रयोगों के लिए यह वांछनीय नहीं है, इसलिए मूल रोटेशन का संकेत दिया गया है (जैसे एक सूचकांक द्वारा; लेख देखें)। लेकिन सरल रोटेशन-स्वतंत्र तुलना के लिए, यह आदर्श लगता है। बेशक, यह जरूरी नहीं कि आदर्श रूप से कुशल हो!


चूंकि बर्स-व्हीलर ट्रांसफॉर्म में स्ट्रिंग के सभी घुमावों की गणना करना शामिल है, यह निश्चित रूप से इष्टतम नहीं होने जा रहा है .. :-)
R .. GitHub STOP HELPING ICE

6

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


हमने इसे एक दिलचस्प कोडिंग अभ्यास के रूप में उपयोग किया है, मुझे यकीन नहीं है कि हम इसका मूल्यांकन करने में सक्षम होंगे;)।
जैशाओ

एफएफटी ने मुझे :) +1 से गाली दी
आमिर

5

किसी ने अभी तक मोडुलो दृष्टिकोण की पेशकश नहीं की है, इसलिए यहां एक है:

static void Main(string[] args)
{
    Console.WriteLine("Rotation : {0}",
        IsRotation("stackoverflow", "ztackoverflow"));
    Console.WriteLine("Rotation : {0}",
        IsRotation("stackoverflow", "ackoverflowst"));
    Console.WriteLine("Rotation : {0}",
        IsRotation("stackoverflow", "overflowstack"));
    Console.WriteLine("Rotation : {0}",
        IsRotation("stackoverflow", "stackoverflwo"));
    Console.WriteLine("Rotation : {0}",
        IsRotation("stackoverflow", "tackoverflwos"));
    Console.ReadLine();
}

public static bool IsRotation(string a, string b)
{
    Console.WriteLine("\nA: {0} B: {1}", a, b);

    if (b.Length != a.Length)
        return false;

    int ndx = a.IndexOf(b[0]);
    bool isRotation = true;
    Console.WriteLine("Ndx: {0}", ndx);
    if (ndx == -1) return false;
    for (int i = 0; i < b.Length; ++i)
    {
        int rotatedNdx = (i + ndx) % b.Length;
        char rotatedA = a[rotatedNdx];

        Console.WriteLine( "B: {0} A[{1}]: {2}", b[i], rotatedNdx, rotatedA );

        if (b[i] != rotatedA)
        {
            isRotation = false;
            // break; uncomment this when you remove the Console.WriteLine
        }
    }
    return isRotation;
}

आउटपुट:

A: stackoverflow B: ztackoverflow
Ndx: -1
Rotation : False

A: stackoverflow B: ackoverflowst
Ndx: 2
B: a A[2]: a
B: c A[3]: c
B: k A[4]: k
B: o A[5]: o
B: v A[6]: v
B: e A[7]: e
B: r A[8]: r
B: f A[9]: f
B: l A[10]: l
B: o A[11]: o
B: w A[12]: w
B: s A[0]: s
B: t A[1]: t
Rotation : True

A: stackoverflow B: overflowstack
Ndx: 5
B: o A[5]: o
B: v A[6]: v
B: e A[7]: e
B: r A[8]: r
B: f A[9]: f
B: l A[10]: l
B: o A[11]: o
B: w A[12]: w
B: s A[0]: s
B: t A[1]: t
B: a A[2]: a
B: c A[3]: c
B: k A[4]: k
Rotation : True

A: stackoverflow B: stackoverflwo
Ndx: 0
B: s A[0]: s
B: t A[1]: t
B: a A[2]: a
B: c A[3]: c
B: k A[4]: k
B: o A[5]: o
B: v A[6]: v
B: e A[7]: e
B: r A[8]: r
B: f A[9]: f
B: l A[10]: l
B: w A[11]: o
B: o A[12]: w
Rotation : False

A: stackoverflow B: tackoverflwos
Ndx: 1
B: t A[1]: t
B: a A[2]: a
B: c A[3]: c
B: k A[4]: k
B: o A[5]: o
B: v A[6]: v
B: e A[7]: e
B: r A[8]: r
B: f A[9]: f
B: l A[10]: l
B: w A[11]: o
B: o A[12]: w
B: s A[0]: s
Rotation : False

[EDIT: 2010-04-12]

पायोत्र ने मेरे कोड में दोष देखा। यह तब त्रुटि करता है जब स्ट्रिंग में पहला वर्ण दो या दो बार होता है। उदाहरण के लिए, के stackoverflowखिलाफ परीक्षण किया गयाowstackoverflow जिसके परिणामस्वरूप गलत था, जब यह सच होना चाहिए।

त्रुटि को स्पॉट करने के लिए धन्यवाद piotr।

अब, यहाँ सही कोड है:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace TestRotate
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Rotation : {0}",
                IsRotation("stackoverflow", "ztackoverflow"));
            Console.WriteLine("Rotation : {0}",
                IsRotation("stackoverflow", "ackoverflowst"));
            Console.WriteLine("Rotation : {0}",
                IsRotation("stackoverflow", "overflowstack"));
            Console.WriteLine("Rotation : {0}",
                IsRotation("stackoverflow", "stackoverflwo"));
            Console.WriteLine("Rotation : {0}",
                IsRotation("stackoverflow", "tackoverflwos"));

            Console.WriteLine("Rotation : {0}",
                IsRotation("stackoverflow", "owstackoverfl"));

            Console.ReadLine();
        }

        public static bool IsRotation(string a, string b)
        {
            Console.WriteLine("\nA: {0} B: {1}", a, b);

            if (b.Length != a.Length)
                return false;

            if (a.IndexOf(b[0]) == -1 )
                return false;

            foreach (int ndx in IndexList(a, b[0]))
            {
                bool isRotation = true;

                Console.WriteLine("Ndx: {0}", ndx);

                for (int i = 0; i < b.Length; ++i)
                {
                    int rotatedNdx = (i + ndx) % b.Length;
                    char rotatedA = a[rotatedNdx];

                    Console.WriteLine("B: {0} A[{1}]: {2}", b[i], rotatedNdx, rotatedA);

                    if (b[i] != rotatedA)
                    {
                        isRotation = false;
                        break;
                    }
                }
                if (isRotation)
                    return true;
            }
            return false;
        }

        public static IEnumerable<int> IndexList(string src, char c)
        {
            for (int i = 0; i < src.Length; ++i)
                if (src[i] == c)
                    yield return i;
        }

    }//class Program
}//namespace TestRotate

यहाँ उत्पादन है:

A: stackoverflow B: ztackoverflow
Rotation : False

A: stackoverflow B: ackoverflowst
Ndx: 2
B: a A[2]: a
B: c A[3]: c
B: k A[4]: k
B: o A[5]: o
B: v A[6]: v
B: e A[7]: e
B: r A[8]: r
B: f A[9]: f
B: l A[10]: l
B: o A[11]: o
B: w A[12]: w
B: s A[0]: s
B: t A[1]: t
Rotation : True

A: stackoverflow B: overflowstack
Ndx: 5
B: o A[5]: o
B: v A[6]: v
B: e A[7]: e
B: r A[8]: r
B: f A[9]: f
B: l A[10]: l
B: o A[11]: o
B: w A[12]: w
B: s A[0]: s
B: t A[1]: t
B: a A[2]: a
B: c A[3]: c
B: k A[4]: k
Rotation : True

A: stackoverflow B: stackoverflwo
Ndx: 0
B: s A[0]: s
B: t A[1]: t
B: a A[2]: a
B: c A[3]: c
B: k A[4]: k
B: o A[5]: o
B: v A[6]: v
B: e A[7]: e
B: r A[8]: r
B: f A[9]: f
B: l A[10]: l
B: w A[11]: o
Rotation : False

A: stackoverflow B: tackoverflwos
Ndx: 1
B: t A[1]: t
B: a A[2]: a
B: c A[3]: c
B: k A[4]: k
B: o A[5]: o
B: v A[6]: v
B: e A[7]: e
B: r A[8]: r
B: f A[9]: f
B: l A[10]: l
B: w A[11]: o
Rotation : False

A: stackoverflow B: owstackoverfl
Ndx: 5
B: o A[5]: o
B: w A[6]: v
Ndx: 11
B: o A[11]: o
B: w A[12]: w
B: s A[0]: s
B: t A[1]: t
B: a A[2]: a
B: c A[3]: c
B: k A[4]: k
B: o A[5]: o
B: v A[6]: v
B: e A[7]: e
B: r A[8]: r
B: f A[9]: f
B: l A[10]: l
Rotation : True

यहाँ लंबोदर दृष्टिकोण है:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IsRotation
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Rotation : {0}",
                IsRotation("stackoverflow", "ztackoverflow"));

            Console.WriteLine("Rotation : {0}",
                IsRotation("stackoverflow", "ackoverflowst"));

            Console.WriteLine("Rotation : {0}",
                IsRotation("stackoverflow", "overflowstack"));
            Console.WriteLine("Rotation : {0}",
                IsRotation("stackoverflow", "stackoverflwo"));

            Console.WriteLine("Rotation : {0}",
                IsRotation("stackoverflow", "owstackoverfl"));

            string strToTestFrom = "stackoverflow";
            foreach(string s in StringRotations(strToTestFrom))
            {
                Console.WriteLine("is {0} rotation of {1} ? {2}",
                    s, strToTestFrom,
                    IsRotation(strToTestFrom, s) );
            }
            Console.ReadLine();
        }

        public static IEnumerable<string> StringRotations(string src)
        {
            for (int i = 0; i < src.Length; ++i)
            {
                var sb = new StringBuilder();
                for (int x = 0; x < src.Length; ++x)
                    sb.Append(src[(i + x) % src.Length]);

                yield return sb.ToString();
            }
        }

        public static bool IsRotation(string a, string b)
        {
            if (b.Length != a.Length || a.IndexOf(b[0]) < 0 ) return false;
            foreach(int ndx in IndexList(a, b[0]))
            {
                int i = ndx;
                if (b.ToCharArray().All(x => x == a[i++ % a.Length]))
                    return true;
            }
            return false;
        }

        public static IEnumerable<int> IndexList(string src, char c)
        {
            for (int i = 0; i < src.Length; ++i)
                if (src[i] == c)
                    yield return i;
        }

    }//class Program

}//namespace IsRotation

यहाँ लंबोदर एप्रोच आउटपुट है:

Rotation : False
Rotation : True
Rotation : True
Rotation : False
Rotation : True
is stackoverflow rotation of stackoverflow ? True
is tackoverflows rotation of stackoverflow ? True
is ackoverflowst rotation of stackoverflow ? True
is ckoverflowsta rotation of stackoverflow ? True
is koverflowstac rotation of stackoverflow ? True
is overflowstack rotation of stackoverflow ? True
is verflowstacko rotation of stackoverflow ? True
is erflowstackov rotation of stackoverflow ? True
is rflowstackove rotation of stackoverflow ? True
is flowstackover rotation of stackoverflow ? True
is lowstackoverf rotation of stackoverflow ? True
is owstackoverfl rotation of stackoverflow ? True
is wstackoverflo rotation of stackoverflow ? True

मुझे नहीं लगता कि int nxx = a.ndexOf (b [0]) के बाद से आपका उत्तर सही है; केवल तभी काम करेंगे जब स्ट्रिंग में b [0] के समान मूल्य वाले अन्य तत्व न हों।
पोट्ट्रर

दोष नोटिस करने के लिए धन्यवाद। अब इसे ठीक कर दिया
माइकल बुएन

3

जैसा कि किसी ने भी C ++ सॉल्यूशन नहीं दिया है। यहाँ यह है:

bool isRotation(string s1,string s2) {

  string temp = s1;
  temp += s1;
  return (s1.length() == s2.length()) && (temp.find(s2) != string::npos);
}

युगल बिंदु: यदि आप लंबाई से मेल नहीं खाते हैं, तो भी आप अपेक्षाकृत महंगे स्ट्रिंग संयोजन कर रहे हैं; आप संदर्भ से s2 पास कर सकते हैं।
टोनी डेलारॉय

2

ओपेरा का सरल पॉइंटर रोटेशन ट्रिक काम करता है, लेकिन यह रनिंग टाइम में सबसे खराब स्थिति में बेहद अक्षम है। बस पात्रों के कई लंबे दोहराए जाने वाले रन के साथ एक स्ट्रिंग की कल्पना करें, अर्थात:

S1 = HELLOHELLOHELLO1HELLOHELLOHELLO2

S2 = HELLOHELLOHELLO2HELLOHELLOHELLO1

"लूप जब तक कोई मिसमैच नहीं होता है, तब एक के बाद एक वृद्धि होती है और फिर से कोशिश करें" एक भयानक दृष्टिकोण है, कम्प्यूटेशनल रूप से।

यह साबित करने के लिए कि आप बहुत अधिक प्रयास के बिना सादे सी में समवर्ती दृष्टिकोण कर सकते हैं, यहाँ मेरा समाधान है:

  int isRotation(const char* s1, const char* s2) {
        assert(s1 && s2);

        size_t s1Len = strlen(s1);

        if (s1Len != strlen(s2)) return 0;

        char s1SelfConcat[ 2 * s1Len + 1 ];

        sprintf(s1SelfConcat, "%s%s", s1, s1);   

        return (strstr(s1SelfConcat, s2) ? 1 : 0);
}

ओवरहेड में O (n) मेमोरी उपयोग की कीमत पर यह रनिंग टाइम में रैखिक है।

(ध्यान दें कि स्ट्रैस का कार्यान्वयन () प्लेटफ़ॉर्म-विशिष्ट है, लेकिन यदि विशेष रूप से ब्रेन-डेड है, तो इसे हमेशा तेज विकल्प जैसे कि बॉयर-मूर एल्गोरिथम के साथ बदला जा सकता है)


1
क्या आपको strstr()O (n + m) वाले किसी भी प्लेटफॉर्म का पता है ? इसके अलावा, अगर मानक (या कुछ और) आपको एक रैखिक चलने के समय की गारंटी नहीं देता है strstr(), तो आप यह दावा नहीं कर सकते कि पूरे एल्गोरिथ्म में रैखिक समय की समानता है।
jpalecek

यही कारण है कि मैंने कहा कि इसे बॉयर-मूर एल्गोरिथ्म द्वारा प्रतिस्थापित किया जा सकता है, जिससे इसे रैखिक समय में चलाया जा सकता है।
22

आपके आवंटित करने की विधि के साथ कुछ संभावित समस्याएं हैं s1SelfConcat: यह केवल C9x के बाद से है कि C, चर सरणी आकार (हालांकि GCC ने इसे बहुत लंबे समय तक अनुमति दी है) की अनुमति देता है, और आप स्टैक पर बड़े तारों को आवंटित करने में परेशानी में पड़ेंगे। Yosef Kreinin ने इस समस्या के बारे में एक बहुत ही मनोरंजक ब्लॉग पोस्ट लिखा । इसके अलावा, आपका समाधान बॉयर-मूर के साथ अभी भी द्विघात समय है; आप केएमपी चाहते हैं।
क्रैगन जेवियर सीटेकर


2

मुझे वह उत्तर पसंद है जो यह जांचता है कि s2 s1 के साथ मिलकर s1 का एक विकल्प है।

मैं एक ऐसा अनुकूलन जोड़ना चाहता था जो अपना लालित्य न खोए।

इसके बजाय स्ट्रिंग को सम्मिलित करने के लिए आप एक सम्मिलित दृश्य का उपयोग कर सकते हैं (मैं अन्य भाषा के लिए नहीं जानता, लेकिन C ++ Boost.Range के लिए इस तरह के विचार प्रदान करता हूं)।

चेक के रूप में अगर एक स्ट्रिंग दूसरे का एक विकल्प है जिसमें रैखिक औसत जटिलता है (सबसे खराब स्थिति जटिलता द्विघात है), इस अनुकूलन को औसत में 2 के कारक द्वारा गति में सुधार करना चाहिए।


2

एक शुद्ध जावा उत्तर (sans null check)

private boolean isRotation(String s1,String s2){
    if(s1.length() != s2.length()) return false;
    for(int i=0; i < s1.length()-1; i++){
        s1 = new StringBuilder(s1.substring(1)).append(s1.charAt(0)).toString();
        //--or-- s1 = s1.substring(1) + s1.charAt(0)
        if(s1.equals(s2)) return true;
    }
    return false;
}

2

और अब पूरी तरह से अलग कुछ करने के लिए।

यदि आप कुछ विवश संदर्भों में वास्तव में तेजी से उत्तर चाहते हैं जब तार एक दूसरे के रोटेशन नहीं होते हैं

  • दोनों स्ट्रिंग्स पर कुछ कैरेक्टर बेस्ड चेकसम (जैसे सभी कैरेक्टर को एक्सरसाइज करना) कंप्यूट करें। यदि हस्ताक्षर भिन्न होते हैं, तो तार एक दूसरे के घूर्णन नहीं होते हैं।

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



1

PHP का उपयोग strlenऔर strposकार्यों में लिखना बहुत आसान है :

function isRotation($string1, $string2) {
    return strlen($string1) == strlen($string2) && (($string1.$string1).strpos($string2) != -1);
}

मुझे नहीं पता कि strposआंतरिक रूप से क्या उपयोग होता है, लेकिन अगर यह केएमपी का उपयोग करता है तो यह समय में रैखिक होगा।


1

एक तार का उलटा। दोनों का FFT लें (उन्हें पूर्णांकों के सरल अनुक्रमों के रूप में मानते हुए)। परिणाम को बिंदुवार एक साथ गुणा करें। उलटा एफएफटी का उपयोग करके वापस ट्रांसफ़ॉर्म करें। परिणाम में एक एकल शिखर होगा यदि तार एक दूसरे के घुमाव हैं - चोटी की स्थिति एक-दूसरे के संबंध में कितनी घुमाएगी, यह इंगित करेगी।


0

ऐसा कुछ क्यों नहीं?


//is q a rotation of p?
bool isRotation(string p, string q) {
    string table = q + q;    
    return table.IndexOf(p) != -1;
}

बेशक, आप अपना खुद का IndexOf () फ़ंक्शन लिख सकते हैं; मुझे यकीन नहीं है कि अगर .NET एक भोले तरीके या तेज़ तरीके से उपयोग करता है।

अनुभवहीन:


int IndexOf(string s) {
    for (int i = 0; i < this.Length - s.Length; i++)
        if (this.Substring(i, s.Length) == s) return i;
    return -1;
}

और तेज:


int IndexOf(string s) {
    int count = 0;
    for (int i = 0; i < this.Length; i++) {
        if (this[i] == s[count])
            count++;
        else
            count = 0;
        if (count == s.Length)
            return i - s.Length;
    }
    return -1;
}

संपादित करें: मुझे कुछ ऑफ-बाय-वन समस्याएं हो सकती हैं; जाँच करने का मन नहीं करता। ;)


0

मैं पर्ल में ऐसा करूंगा :

sub isRotation { 
     return length $_[0] == length $_[1] and index($_[1],$_[0],$_[0]) != -1; 
}

0
int rotation(char *s1,char *s2)
{
    int i,j,k,p=0,n;
    n=strlen(s1);
    k=strlen(s2);
    if (n!=k)
        return 0;
    for (i=0;i<n;i++)
    {
        if (s1[0]==s2[i])
        {
            for (j=i,k=0;k<n;k++,j++)
            {
                if (s1[k]==s2[j])
                    p++;
                if (j==n-1)
                    j=0;
            }
        }
    }
    if (n==p+1)
      return 1;
    else
      return 0;
}

0

नवगठित स्ट्रिंग में मौजूद है या नहीं यह जाँचने के लिए KMP एल्गोरिथ्म केstring1 साथ जुड़ें string2और उपयोग करें । क्योंकि केएमपी की समय जटिलता इससे कम है ।string2substr

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