जांचें कि क्या कोई आइसोमॉर्फ सबस्ट्रिंग है


12

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

दो शब्द आइसोमॉर्फ हैं यदि उनके पास अक्षर दोहराव का समान पैटर्न है। उदाहरण के लिए, दोनों ESTATEऔर DUELEDपैटर्न हैabcdca

ESTATE
DUELED

abcdca

क्योंकि अक्षर 1 और 6 समान हैं, अक्षर 3 और 5 समान हैं, और आगे कुछ भी नहीं है। इसका मतलब यह भी है कि शब्द एक प्रतिस्थापन सिफर से संबंधित हैं, यहां मिलान के साथ E <-> D, S <-> U, T <-> E, A <-> L

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

इनपुट: a..zA..Z से अक्षरों के दो गैर-खाली तार जो प्रति पंक्ति एक स्ट्रिंग। यह स्टैंडर्ड इनपुट से आएगा।

आउटपुट दूसरी स्ट्रिंग का एक विकल्प जो पहली स्ट्रिंग के साथ एक आइसोमॉर्फ है, अगर ऐसी कोई चीज मौजूद है। अन्यथा आउटपुट "नहीं!"।

नियम आपका कोड इनपुट की कुल लंबाई में रैखिक समय में चलना चाहिए।

स्कोर आपका स्कोर आपके कोड में बाइट्स की संख्या है। सबसे कम बाइट्स जीतता है।


उदाहरण इनपुट और आउटपुट

adca
ddaddabdaabbcc

dabd

टिप

वहाँ एक नहीं कम से कम है कि जटिल, व्यावहारिक रूप से तेजी से और इस समस्या का रैखिक समय समाधान।


@AlexA। मुझे लगता है कि किसी ने मुझसे कहा कि यदि आप रनिंग टाइम / जटिलता को प्रतिबंधित करते हैं तो यह कोड-चैलेंज होना चाहिए। अगर यह निश्चित रूप से गलत है तो मैं इसे बदलकर खुश हूं।

7
यदि रन समय एक नियम से बंधा हुआ है और स्कोरिंग को प्रभावित नहीं करता है, तो कोड-गोल्फ कोड-चुनौती से बेहतर फिट है।
डेनिस

रैखिक समय का मतलब है कि इसे O (m + n) और O (mxn) नहीं होना चाहिए और न ही O (mx (nm)) जहां m, n पहली और दूसरी स्ट्रिंग की लंबाई है?
कुछ उपयोगकर्ता

@someuser हां इसका मतलब हे (m + n) है।

1
@BetaDecay देखें "दो तार एक्स और वाई को देखते हुए, एक्स अब वाई के मुकाबले नहीं है, यह निर्धारित करने के लिए कार्य है कि क्या वाई का एक विकल्प है जो एक्स के साथ एक आइसोमॉर्फ है।"

जवाबों:


8

अजगर 2, 338 326 323 321 310 306 297 293 290 289 280 279 266 264 259 237 230 229 226 223 222 220 219 (217 260 238 231 228 225 223 221 220 0 बाहर निकलने की स्थिति के साथ 218)

exec'''s=raw_input()
S=[M-s.rfind(c,0,M)for M,c in enumerate(s)]
k=0
j=x=%s
while k<=M+x:
 if S[k]>j<W[j]or S[k]==W[j]:
    k+=1;j+=1;T+=[j]
    if j-L>x:print s[k-j:k];z
 else:j=T[j]
'''*2%('-1;T=[0];W=S;L=M',0)
print'No!'

एल्गोरिथ्म केएमपी का एक रूपांतर है, जो चरित्र मिलान के लिए सूचकांक आधारित परीक्षण का उपयोग करता है। मूल विचार यह है कि यदि हम स्थिति में बेमेल X[i]हो जाते हैं, तो हम मैच के लिए अगले संभावित स्थान पर सबसे लंबे समय तक प्रत्यय के अनुसार वापस आ सकते X[:i]हैं X

बाएं से दाएं कार्य करते हुए, हम प्रत्येक वर्ण को उस वर्ण की सबसे हाल की पिछली घटना से दूरी के बराबर एक सूचकांक प्रदान करते हैं, या यदि कोई पिछली घटना नहीं है, तो हम वर्तमान स्ट्रिंग उपसर्ग की लंबाई लेते हैं। उदाहरण के लिए:

MISSISSIPPI
12313213913

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

केएमपी एल्गोरिथ्म थोड़ा सरल हो जाता है क्योंकि हम पहले चरित्र पर एक बेमेल नहीं प्राप्त कर सकते हैं।

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

नोट: अभिकलन सूचकांकों के लिए, हम उपयोग कर सकते हैं str.rfind(जैसा कि एक शब्दकोश का उपयोग करते हुए मेरे पहले के दृष्टिकोण के विपरीत) और अभी भी रैखिक जटिलता है, यह मानते हुए कि str.rfindअंत से खोज शुरू होती है (जो केवल एकमात्र कार्यान्वयन विकल्प लगता है) - वर्णमाला में प्रत्येक वर्ण के लिए , हमें कभी भी स्ट्रिंग के एक ही हिस्से को दो बार नहीं बदलना पड़ता है, इसलिए एक ऊपरी सीमा (वर्णमाला का आकार) * (स्ट्रिंग का आकार) तुलना है।

चूंकि कोडिंग को गोल्फिंग के दौरान काफी बाधित किया गया था, इसलिए यहां एक पुराना (293 बाइट) समाधान है जिसे पढ़ना थोड़ा आसान है:

e=lambda a:a>i<W[i]or a==W[i]
exec('s=raw_input();S=[];p={};M=i=0\nfor c in s:S+=[M-p.get(c,-1)];p[c]=M;M+=1\nW=S;L=M;'*2)[:-9]
T=[0]*L
k=1
while~k+L:
 if e(W[k]):i+=1;k+=1;T[k]=i
 else:i=T[i]
m=i=0
while m+i<M:
 if e(S[m+i]):
    if~-L==i:print s[m:m+L];z
    i+=1
 else:m+=i-T[i];i=T[i]
print'No!'

eसमारोह परीक्षण पात्रों में से तुल्यता। execबयान सूचकांक प्रदान करती है और कुछ चर initialisations करता है। पहला लूप Xबैक वैल्यू गिरता है और दूसरा लूप स्ट्रिंग सर्च करता है।

अपडेट: यहां एक संस्करण है जो एक बाइट की कीमत पर, सफाई से बाहर निकलता है:

r='No!'
exec'''s=raw_input()
S=[M-s.rfind(c,0,M)for M,c in enumerate(s)]
k=0
j=x=%s
while k<=M+x:
 if S[k]>j<W[j]or S[k]==W[j]:
    k+=1;j+=1;T+=[j]
    if j-L>x:r=k=s[k-j:k]
 else:j=T[j]
'''*2%('-1;T=[0];W=S;L=M',0)
print r

मुझे लगता है कि आप पायथन 3 करके बाइट बचा सकते हैं। r=raw_inputबनाम आर = input4 बाइट और प्रिंट पर कोष्ठक की बचत होती है केवल 3. लागत
Maltysen

@Maltysen टिप्पणी के लिए धन्यवाद। इसे लिखते समय मैंने पायथन 3 पर विचार नहीं किया, लेकिन लागत और बचत के रूप में, अतिरिक्त 2 बाइट की लागत है क्योंकि आप पायथन 3 में इंडेंटेशन के लिए रिक्त स्थान और टैब नहीं मिला सकते हैं
मिच श्वार्ट्ज

@ मैटलीन बस फॉलो करने के लिए, इस मुद्दे पर अब टैब नहीं बल्कि ब्रैकेट हैं exec
मिच श्वार्ट्ज

यह एक बहुत अच्छा जवाब है! मैं इसे अब cjam में देखने के लिए तत्पर हूं :)

6

पायथन 3, 401 बाइट्स

import string,itertools
X=input()
Y=input()
x=len(X)
t=[-1]+[0]*~-x
j=2
c=0
while j<x:
 if X[j-1]==X[c]:c+=1;t[j]=c;j+=1
 elif c>0:c=t[c]
 else:t[j]=0;j+=1
s=string.ascii_letters
*b,=map(s.find,X)
for p in itertools.permutations(s):
 m=i=0
 while m+i<len(Y):
  if p[b[i]]==Y[m+i]:
   if~-x==i:print(Y[m:m+x]);exit()
   else:i+=1
  else:
   if-1<t[i]:m+=i-t[i];i=t[i]
   else:i=0;m+=1
else:print("No!")

यह अभी भी ज्यादातर अनगढ़ है, लेकिन मुझे लगता है कि इसे काम करना चाहिए। कोर एल्गोरिथ्म KMP है , साथ ही एक अतिरिक्त कारक जो वर्णमाला के आकार में तथ्यात्मक है (जो ठीक है, क्योंकि वर्णमाला स्थिर है)। दूसरे शब्दों में, यह एक / पूरी तरह से अव्यावहारिक रैखिक एल्गोरिदम होना चाहिए।

विश्लेषण के साथ मदद करने के लिए यहां कुछ टिप्पणियां दी गई हैं:

# KMP failure table for the substring, O(n)
t=[-1]+[0]*~-x
j=2
c=0
while j<x:
 if X[j-1]==X[c]:c+=1;t[j]=c;j+=1
 elif c>0:c=t[c]
 else:t[j]=0;j+=1

# Convert each char to its index in a-zA-Z, O(alphabet * n)
s=string.ascii_letters
*b,=map(s.find,X)

# For every permutation of letters..., O(alphabet!)
for p in itertools.permutations(s):
 # Run KMP, O(n)
 m=i=0
 while m+i<len(Y):
  if p[b[i]]==Y[m+i]:
   if~-x==i:print(Y[m:m+x]);exit()
   else:i+=1
  else:
   if-1<t[i]:m+=i-t[i];i=t[i]
   else:i=0;m+=1
else:print("No!")

परीक्षण के लिए, आप की sतुलना में छोटे वर्णमाला के साथ बदल सकते हैं string.ascii_letters


2

APL (Dyalog) , 32 बाइट्स

यह एक infix फंक्शन है, X को लेफ्ट लॉजिक के रूप में और Y को राइट लेग के रूप में लेते हैं।

{(s,⊂'No!')⊃⍨(⍳⍨¨s←⍵,/⍨≢⍺)⍳⊂⍳⍨⍺}

इसे ऑनलाइन आज़माएं!

{} अनाम लंबोदर जहां और तर्कों का प्रतिनिधित्व करते हैं (एक्स और वाई)

⍳⍨⍺ɩ एक्स के ndex सेल्फी ( ɩ एक्स में एक्स के तत्वों की पहली घटना के ndices)

 संलग्न करें ताकि हम उस पूरे पैटर्न को देख सकें

(…… )⍳Ndex की पहली घटना है कि…

  ≢⍺ एक्स की टैली (लंबाई)

  ⍵,/⍨ वाई के उस आकार के सभी सब्सट्रेटिंग (उन पर जलाए जाने की कमी, लेकिन यह एक विकल्प नहीं है)

  s←s( s ubstrings के लिए)  स्टोर करें

  ⍳⍨¨उनमें से प्रत्येक की ɩ ndex सेल्फी

 अब हमारे पास पहले पैटर्न का सूचकांक है, या 1 + पैटर्न की संख्या अगर कोई मैच नहीं मिला

()⊃⍨ उस इंडेक्स का उपयोग…

  ⊂'No!' संलग्न स्ट्रिंग (ताकि यह एक तत्व के रूप में कार्य करे)

  s, के साथ शुरू हुआ s

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