ตรวจสอบว่ามีสตริงย่อย isomorph


12

คำถามนี้เป็นส่วนขยายของตรวจสอบว่าคำ isomorphs และคัดลอกส่วนแรกของมันเพื่อให้คำจำกัดความของ isomorph

คำสองคำคือisomorphsหากพวกเขามีรูปแบบซ้ำของตัวอักษรเดียวกัน ตัวอย่างเช่นทั้งสองESTATEและDUELEDมีรูปแบบabcdca

ESTATE
DUELED

abcdca

เพราะตัวอักษร 1 และ 6 เหมือนกันตัวอักษร 3 และ 5 เหมือนกันและไม่มีอะไรเพิ่มเติม E <-> D, S <-> U, T <-> E, A <-> Lนอกจากนี้ยังหมายคำที่เกี่ยวข้องโดยตัวเลขทดแทนที่นี่ด้วยการจับคู่

รับสองสตริง X และ Y โดย X ไม่เกิน Y งานจะต้องตรวจสอบว่ามีสตริงย่อยของ Y ซึ่งเป็น isomorph กับ X หรือไม่

อินพุต:สองตัวอักษรที่ไม่ว่างเปล่าจาก a..zA..Z ซึ่งหนึ่งสตริงต่อบรรทัด สิ่งนี้จะมาจากอินพุตมาตรฐาน

เอาท์พุทสตริงย่อยของสตริงที่สองซึ่งเป็น isomorph กับสตริงแรกถ้าสิ่งนั้นมีอยู่ มิฉะนั้นเอาท์พุท "ไม่!"

กฎรหัสของคุณจะต้องทำงานในเวลาเชิงเส้นในความยาวทั้งหมดของการป้อนข้อมูล

คะแนนคะแนนของคุณคือจำนวนไบต์ในรหัสของคุณ ไบต์ที่น้อยที่สุดจะเป็นผู้ชนะ


ตัวอย่างอินพุตและเอาต์พุต

adca
ddaddabdaabbcc

dabd

ปลาย

มีอย่างหนึ่งอย่างน้อยไม่ว่าซับซ้อนในทางปฏิบัติได้อย่างรวดเร็วและวิธีการแก้ปัญหาเส้นเวลาเพื่อแก้ไขปัญหานี้


@AlexA ฉันคิดว่ามีคนบอกฉันว่าถ้าคุณ จำกัด เวลาทำงาน / ความซับซ้อนมันควรจะเป็นรหัสที่ท้าทาย ฉันมีความสุขที่จะเปลี่ยนมันถ้ามันผิดแน่นอน

7
หากเวลาการทำงานถูก จำกัด โดยกฎและไม่มีผลต่อการให้คะแนนรหัสการเล่นกอล์ฟนั้นดีกว่าการท้าทายรหัส
Dennis

เวลาเชิงเส้นหมายความว่ามันต้องเป็น O (m + n) และไม่ใช่ O (mxn) หรือ O (mx (nm)) โดยที่ m, n มีความยาวของสตริงที่หนึ่งและที่สอง?
ผู้ใช้บางคน

@someuser ใช่มันหมายถึง O (m + n)

1
@BetaDecay ดู "รับสองสตริง X และ Y โดย X ไม่เกิน Y งานคือการตรวจสอบว่ามีสตริงย่อยของ Y ซึ่งเป็น isomorph กับ X. "

คำตอบ:


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 218 0 สถานะออก)

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!'

อัลกอริทึมเป็นรูปแบบของ KMP โดยใช้การทดสอบแบบอิงดัชนีสำหรับการจับคู่อักขระ แนวคิดพื้นฐานคือว่าถ้าเราได้รับไม่ตรงกันในตำแหน่งX[i]แล้วเราสามารถถอยกลับไปยังสถานที่ที่เป็นไปได้ต่อไปสำหรับการแข่งขันเป็นไปตามคำต่อท้ายที่ยาวที่สุดของX[:i]ที่เป็น isomorphic Xคำนำหน้าของ

ทำงานจากซ้ายไปขวาเรากำหนดดัชนีแต่ละตัวให้เท่ากับระยะทางไปยังเหตุการณ์ล่าสุดที่เกิดขึ้นล่าสุดของตัวละครนั้นหรือหากไม่มีเหตุการณ์ก่อนหน้านี้เราจะใช้ความยาวของคำนำหน้าสตริงปัจจุบัน ตัวอย่างเช่น:

MISSISSIPPI
12313213913

ในการทดสอบว่าอักขระสองตัวตรงกันหรือไม่เราเปรียบเทียบดัชนีปรับอย่างเหมาะสมสำหรับดัชนีที่มากกว่าความยาวของสตริงปัจจุบัน (ย่อย)

อัลกอริทึม KMP จะง่ายขึ้นเล็กน้อยเนื่องจากเราไม่สามารถจับคู่อักขระตัวแรกไม่ตรงกัน

โปรแกรมนี้จะส่งออกการแข่งขันครั้งแรกถ้ามีอยู่ ฉันใช้ข้อผิดพลาดรันไทม์เพื่อออกในกรณีที่มีการแข่งขัน แต่รหัสสามารถแก้ไขได้อย่างง่ายดายเพื่อออกอย่างหมดจดในราคาไบต์บาง

หมายเหตุ:สำหรับการคำนวณดัชนีเราสามารถใช้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

ฉันคิดว่าคุณสามารถบันทึกไบต์ด้วยการทำ python3 r=raw_inputvs. r = inputประหยัด 4 ไบต์และ parens on print เท่านั้นมีค่าใช้จ่าย 3
Maltysen

@ Maltysen ขอบคุณสำหรับความคิดเห็น ฉันไม่ได้พิจารณา Python 3 เมื่อเขียนสิ่งนี้ แต่สำหรับค่าใช้จ่ายและการประหยัดมีค่าใช้จ่ายเพิ่มเติม 2 ไบต์เนื่องจากคุณไม่สามารถรวมช่องว่างและแท็บสำหรับการเยื้องใน Python 3 ได้
Mitch Schwartz

@Maltysen เพียงเพื่อติดตามปัญหาก็คือแท็บตอนนี้ไม่ execแต่วงเล็บ
Mitch Schwartz

นี่เป็นคำตอบที่ยอดเยี่ยมจริงๆ! ฉันหวังว่าจะเห็นมันใน cjam ตอนนี้ :)

6

Python 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!")

สำหรับการทดสอบคุณสามารถแทนที่ด้วยตัวอักษรขนาดเล็กกว่าsstring.ascii_letters


2

APL (Dyalog) 32 ไบต์

นี่คือฟังก์ชั่น infix โดยให้ X เป็นอาร์กิวเมนต์ซ้ายและ Y เป็นอาร์กิวเมนต์ที่ถูกต้อง

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

ลองออนไลน์!

{} แลมบ์ดานิรนามที่และเป็นตัวแทนของข้อโต้แย้ง (X และ Y)

⍳⍨⍺ɩ nDex เซลฟีของ X ( ɩ ndices ของเกิดขึ้นครั้งแรกขององค์ประกอบของ X ใน X)

 ล้อมรอบเพื่อให้เราสามารถมองหาลวดลายทั้งหมดได้

(... )⍳ex ndex ของการเกิดขึ้นครั้งแรกใน ...

  ≢⍺ tally (ความยาว) ของ X

  ⍵,/⍨ สตริงย่อยทั้งหมดของขนาดนั้นของ Y (การลดความต่อเนื่องของการลดความสว่างของสิ่งเหล่านั้น แต่นั่นไม่ใช่ -op)

  s← เก็บในs(สำหรับs ubstrings)

  ⍳⍨¨ɩ ndex selfie ของแต่ละคน

 ตอนนี้เรามีดัชนีของรูปแบบแรกหรือ 1 + จำนวนของรูปแบบหากไม่พบที่ตรงกัน

(... )⊃⍨ ใช้ดัชนีนั้นเพื่อเลือกจาก ...

  ⊂'No!' สตริงที่ล้อมรอบ (เพื่อให้มันทำหน้าที่เป็นองค์ประกอบเดียว)

  s, ผนวกกับ s

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.