ค้นหาการวนซ้ำที่ยาวที่สุด


9

กำหนดสตริงผมอยากจะหาที่ยาวที่สุดในการทำซ้ำ (อย่างน้อยสองครั้ง) subsequence นั่นคือผมอยากจะพบสตริงซึ่งเป็น subsequence (ที่ไม่จำเป็นต้องเป็นที่ต่อเนื่องกัน) ของเช่นว่าw' นั่นคือคือสตริงที่แบ่งครึ่งปรากฏเป็นสองเท่าในแถว โปรดทราบว่าคือองค์ประกอบของแต่ไม่จำเป็นต้องเป็นสตริงย่อยswsw=wwwws

ตัวอย่าง:

สำหรับ 'ababccabdc' มันจะเป็น 'abcabc' เพราะ 'abc' = 'abc' และ 'abc' จะปรากฏขึ้น (อย่างน้อย) สองครั้งใน 'ababccabdc'

สำหรับ 'addbacddabcd' ตัวเลือกหนึ่งคือ 'dddd' เพราะ 'dd' ปรากฏขึ้นสองครั้ง (ฉันไม่สามารถใช้ตัวอักษรเดียวกันหลาย ๆ ครั้งได้ แต่ที่นี่ฉันมี 4 'd ดังนั้นมันก็โอเค) แต่มันก็ดีกว่า 4 ความยาว 8: 'abcdabcd' เนื่องจาก 'abcd' เป็นซับสตริงของ 'addbacddabcd' ที่ปรากฏสองครั้ง

ฉันสนใจที่จะหาลำดับการวนซ้ำที่ยาวที่สุด นี่เรียกอีกอย่างว่า "การค้นหาสแควร์ที่ยาวที่สุด / ใหญ่ที่สุด" แต่ฉันได้อ่านบทความมากมายที่สแควร์ถูกกำหนดไว้สำหรับสตริงย่อยและไม่ได้สำหรับการเรียงลำดับ

ฉันสามารถใช้อัลกอริทึมแรงเดรัจฉานที่จะใช้โดยวนซ้ำตัวเลือกทั้งหมดสำหรับเบรกพอยต์ในสตริงและจากนั้นฉันจะมีสองสายที่ฉันจะมองหาส่วนประกอบที่ใหญ่ที่สุด / ยาวที่สุดทั่วไป แต่การตรวจสอบแต่ละจะใช้เวลาโดยใช้เทคนิคการเขียนโปรแกรมแบบไดนามิกเพื่อให้ตลอดเวลาจะเป็น3) ผมพบว่าขั้นตอนวิธีการที่มีประสิทธิภาพมากขึ้นสำหรับ subsequence ทั่วไปที่ยาวที่สุดซึ่งจะใช้เวลาดังนั้นเวลาทำงานจะเป็นn})O(n3)O(n2)O(n3)O(n2logn)O(n3logn)

ฉันกำลังมองหาอัลกอริทึมที่มีประสิทธิภาพมากขึ้นสำหรับปัญหาการวนซ้ำที่ยาวที่สุด บางทีความคิดของฉันในการวนซ้ำจุดพักทั้งหมดทำให้เสียเวลามากเกินไปและสามารถลดการทำซ้ำให้น้อยลงได้ หรือบางทีอัลกอริทึมที่มีทัศนคติที่แตกต่างสามารถแก้ปัญหานี้ได้

ฉันค้นหาในวารสารและคำถามก่อนหน้ามากมายและผลลัพธ์ส่วนใหญ่ที่ฉันพบมีเกี่ยวกับสตริงย่อยและไม่เกี่ยวกับการเรียงลำดับ

ฉันยังอ่านด้วยว่าสิ่งนี้สามารถทำได้โดยใช้ต้นไม้ต่อท้าย แต่นี่ก็เกี่ยวข้องกับสารตั้งต้นและฉันไม่แน่ใจว่าแนวคิดดังกล่าวสามารถขยายออกไปได้

ฉันกำลังมองหาวิธีการแก้ปัญหาที่วิ่งในเวลา2) หากมีอยู่ในเวลาว่าจะดียิ่งขึ้น (ผมไม่แน่ใจว่าถ้าเช่นมี)O(n2)O(nlogn)


4
ค้นหาต้นไม้ต่อท้ายหรืออาร์เรย์ต่อท้าย
นามแฝง

1
ก็ไม่น่ามากว่าเรียลไทม์อัลกอริทึมที่มีอยู่สำหรับปัญหานี้เพราะถ้ามันไม่คุณสามารถใช้มันเพื่อเอาชนะอัลกอริทึมที่รู้จักกันดีที่สุดสำหรับการค้นหา LCS ของทั้งสอง length-สายและดังนี้ รูปแบบสตริงที่คือสำเนาของตัวละครที่ไม่ปรากฏทั้งในหรือและเรียกใช้ของคุณเรียลไทม์อัลกอริทึมที่มัน ทั้ง "แบ่งเท่า ๆ กัน" ของลำดับการทำซ้ำที่ยาวที่สุดจะต้องเริ่มต้นด้วยดังนั้นครึ่งหนึ่งมาจากแต่ละและo(n2)nuvxuxvxn+1$uvo(n2)xuvแก้ปัญหา LCS
j_random_hacker

@j_random_hacker LCS สามารถแก้ไขได้ในโดยใช้ Suffix Tree หรือในโดยใช้แฮชกลิ้ง O(n+m)O(nlogn)
Evil

@Evil: ฉันยังไม่เห็นว่าคุณช่วยให้รายละเอียดเพิ่มเติมเล็กน้อย? (คุณแน่ใจหรือไม่ว่าคุณไม่ได้นึกถึงสตริงย่อยที่ยาวที่สุดซึ่งสามารถแก้ไขได้ในช่วงเวลาที่ซับซ้อนเหล่านั้น)
j_random_hacker

@j_random_hacker ฉันคิดว่าคุณกำลังเปรียบเทียบการมุ่งเป้าไปที่กับ LCS (ต่อเนื่อง) แต่ที่นี่ที่คุณพูดถึงใช่ฉันยังไม่เคยเห็นวิธีการแก้ปัญหาการทำงานใน n ^ 2 สำหรับผลลัพธ์ที่พบบ่อยที่สุด (ฉันได้พบ โค้ดการเขียนโปรแกรมแบบไดนามิกหนึ่งรหัสแพร่กระจายผ่านหลายหน้าซึ่งมีข้อบกพร่องคล้ายกับคำตอบ downvote) ดังนั้นฉันเข้าใจผิดความคิดเห็นของคุณขอโทษ o(n2)
Evil

คำตอบ:


-1

นี่คือโซลูชันการเขียนโปรแกรมแบบไดนามิก

สมมติว่าสายป้อนเป็นx_n สร้างตารางซึ่งแถวและคอลัมน์ถูกจัดทำดัชนีโดย (โดยที่คือความยาวของสตริง) บรรจุโดยกฎ คำตอบคือN]x1xnT0,,nn

T[i,j]={0if i=0 or j=0,T[i1,j1]+1if xi=xj and ij,max(T[i1,j],T[i,j1])otherwise.
T[n,n]

สมมติว่าเราอยู่ที่กับและเงื่อนไขในคำสั่งของคุณเป็นจริง จากนั้นก็หมายความว่าตัวละครที่ตำแหน่งเป็นส่วนหนึ่งของทั้งสององค์ประกอบ i,ji=j+1ifdp[i][j] = dp[i - 1][j - 1] + 1i1=j
j_random_hacker

3
ยินดีต้อนรับสู่วิทยาการคอมพิวเตอร์! โปรดได้รับการกำจัดของรหัสที่มาและแทนที่ด้วยความคิดรหัสเทียมและข้อโต้แย้งของความถูกต้อง ดูที่นี่และที่นี่สำหรับการสนทนาเมตาที่เกี่ยวข้อง
Raphael

@Raphael สูตรเรียกซ้ำไม่นับเป็นซอร์สโค้ด
หมายเลข 945

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