โปรแกรม Word ตัวประกอบใน


12

รับสองสตริงS1,S2เราเขียนS1S2สำหรับการต่อกัน ได้รับสตริงSและจำนวนเต็มk1เราเขียน(S)k=SSSสำหรับการเรียงต่อกันของkสำเนาของSSตอนนี้รับสายเราสามารถใช้สัญกรณ์นี้เพื่อ 'บีบอัด' มันคือAABAABอาจจะเขียนเป็น((A)2B)2 . ลองเรียกน้ำหนักของการบีบอัดตามจำนวนตัวอักษรที่ปรากฏในนั้นดังนั้นน้ำหนักของ((A)2B2)คือสองและน้ำหนักของ(AB)2A (การบีบอัดของABABA ) คือสาม (Aแยกต่างหากจะนับแยกต่างหาก)

ตอนนี้ให้พิจารณาปัญหาของการคำนวณการบีบอัด 'เบาที่สุด' ของสตริงSด้วย|S|=n n หลังจากคิดว่ามีวิธีการเขียนโปรแกรมแบบไดนามิกที่ชัดเจนซึ่งทำงานในO(n3logn)หรือO(n3)ขึ้นอยู่กับวิธีที่แน่นอน

อย่างไรก็ตามฉันได้รับแจ้งว่าปัญหานี้สามารถแก้ไขได้ในเวลาO(n2logn)แม้ว่าฉันจะไม่สามารถหาแหล่งข้อมูลเกี่ยวกับวิธีการทำเช่นนี้ได้ ปัญหานี้ได้รับจากการประกวดการเขียนโปรแกรมเมื่อเร็ว ๆ นี้ (ปัญหา K ที่นี่สองหน้าสุดท้าย) ในระหว่างการวิเคราะห์อัลกอริทึมO(n3logn)ถูกนำเสนอและในตอนท้ายกล่าวถึงขอบเขตกำลังสองหลอก ( ที่นี่ที่เครื่องหมายสี่นาที) น่าเสียดายผู้นำเสนอเพียงเรียกว่า 'คำศัพท์ที่ซับซ้อน combinatorics lemma' ดังนั้นตอนนี้ฉันมาที่นี่เพื่อขอคำตอบ :-)


SS=Xa=Yb Z gcd ( | X | , | Y | ) X Y S = X a S Y S = Y b Y X | X |S=Z|S|/gcd(|X|,|Y|)Zgcd(|X|,|Y|)XYS=XaSYS=Ybจากนั้นคุณจะต้องลองใช้คำนำหน้าของซึ่งมีความยาวที่แบ่ง. YX|X|
j_random_hacker

ปัญหาคือว่าแม้หลังจากลดไปได้ทั้งหมดแล้วคุณยังจำเป็นต้องรวมคำตอบลูกบาศก์ลูกบาศก์ต่อส่วนย่อย (เช่น ) ดังนั้นยังคงมีบางงานพิเศษที่จะทำหลังจากที่ ... D P [ l , r ] = ขั้นต่ำk D P [ l , k ] + D P [ k + 1 , r ]XaDP[l,r]=minkDP[l,k]+DP[k+1,r]
ทิมอน Knigge

ฉันเห็นสิ่งที่คุณหมายถึง ฉันคิดว่าคุณต้องการความสัมพันธ์แบบครอบงำที่กำจัดค่าบางค่าจากการทดสอบ - แต่ฉันไม่สามารถคิดได้ โดยเฉพาะอย่างยิ่งฉันพิจารณาสิ่งต่อไปนี้สมมติว่ามีตัวประกอบที่เหมาะสมที่สุดด้วย ; เป็นไปได้หรือไม่ว่ามีวิธีแก้ปัญหาที่ดีที่สุดซึ่งเป็นปัจจัยในฐานะกับ ? แต่น่าเสียดายที่คำตอบคือใช่สำหรับ ,มี factorisation ที่ดีที่สุดแต่ factorisation ที่ดีที่สุดที่ไม่ซ้ำกันสำหรับคือ 2S [ 1 .. i ]kS[1..i] k > 1 S X Y j Z j < k S = A B A B C A B C S [ 1..4 ] ( A B ) 2 S A B ( A B C ) 2S[1..i]=XYkk>1SXYjZj<kS=ABABCABCS[1..4](AB)2SAB(ABC)2
j_random_hacker

คำตอบ:


1

ถ้าฉันไม่เข้าใจคุณผิดฉันคิดว่าการคำนวณต้นทุนขั้นต่ำสามารถคำนวณได้ในเวลาดังต่อไปนี้O(n2)

สำหรับแต่ละดัชนี i เราจะคำนวณกลุ่มของค่าสำหรับดังนี้ ให้เป็นจำนวนเต็มที่เล็กที่สุดซึ่งมีจำนวนเต็มพอใจสำหรับนี้โดยเฉพาะปล่อยให้เป็นใหญ่ที่สุดด้วยคุณสมบัตินี้ หากไม่มีอยู่ให้ตั้งค่าเพื่อให้เรารู้ว่ามีค่าศูนย์สำหรับดัชนีนี้(pi,ri)=1,2,pi11r2

S[irpi1+1,ipi1]=S[i(r1)pi1+1,i].
pi1ri1rpiLi=0(pi,ri)

ให้เป็นจำนวนเต็มที่เล็กที่สุดที่ใหญ่กว่าน่าพอใจเช่นเดียวกัน สำหรับบาง2 เช่นเดียวกับก่อนที่จะใช้จะเป็นสูงสุดคนหนึ่งที่ได้รับการแก้ไข 2 โดยทั่วไปเป็นจำนวนดังกล่าวมีขนาดเล็กที่สุดอย่างเคร่งครัดใหญ่กว่าell-1} ถ้าไม่มีเช่นอยู่แล้วell-1pi2(ri11)pi1

S[iri2pi2+1,ipi2]=S[i(ri21)pi2+1,i]
ri22ri2pi2pi(ri11)pi1piLi=1

โปรดทราบว่าสำหรับแต่ละดัชนีฉันเรามีเนื่องจากค่าเพิ่มขึ้นเรขาคณิตกับ\(หากมีอยู่จริงมันไม่ใช่แค่ใหญ่กว่าแต่ใหญ่กว่านั้นอย่างน้อยสิ่งนี้ทำให้เกิดการเพิ่มขึ้นทางเรขาคณิต )Li=O(log(i+1))pipi+1(ri1)pipi/2

สมมติว่าตอนนี้เรามอบค่าทั้งหมดให้เรา ต้นทุนขั้นต่ำจะได้รับจากการเกิดซ้ำ ด้วยความเข้าใจว่าสำหรับเราตั้ง+ ตารางสามารถเติมเต็มในเวลา(pi,ri)

dp(i,j)=min{dp(i,j1)+1,min(dp(i,jrjpj)+dp(jrjpj+1,jpj))}
i>jdp(i,j)=+O(n2+njLj)

เราได้สังเกตเห็นแล้วว่าโดย จำกัด ขอบเขตผลรวมตามคำศัพท์ แต่ที่จริงถ้าเราดูผลรวมทั้งหมดเราสามารถพิสูจน์สิ่งที่คมชัดกว่าjLj=O(jlog(j+1))=Θ(nlogn)

พิจารณาคำต่อท้ายต้นไม้ของสิ่งที่ตรงกันข้ามของ (กล่าวคือต้นไม้คำนำหน้าของ S) เราจะเรียกเก็บเงินผลงานแต่ละรายการไปยัง sumไปยังขอบของเพื่อให้แต่ละส่วนได้รับการเรียกเก็บเงินไม่เกินครั้งเดียว ชาร์จแต่ละขอบเล็ดลอดออกมาจากและมุ่งหน้าไปยังญ) นี่เป็นใบของต้นไม้คำนำหน้าสอดคล้องกับและ NCA หมายถึงบรรพบุรุษที่ใกล้ที่สุดT(S)SiLiT(S)pijnca(v(i),v(ipij))v(ipij)v(i)S[1..i]

นี้แสดงให้เห็นว่า(n) ค่าสามารถคำนวณได้ในเวลาโดยการสำรวจเส้นทางของทรีต่อท้าย แต่ฉันจะให้รายละเอียดในการแก้ไขในภายหลังหากใครสนใจO(iLi)=O(n)(pij,rij)O(n+iLi)

แจ้งให้เราทราบหากนี่เหมาะสม


-1

มีสตริงเริ่มต้น S ของคุณที่มีความยาว n นี่คือรหัสเทียมของวิธีการ

next_end_bracket = n
for i in [0:n]: # main loop

    break if i >= length(S) # due to compression
    w = (next_end_bracket - i)# width to analyse

    for j in [w/2:0:-1]: # period loop, look for largest period first
        for r in [1:n]: # number of repetition loop
            if i+j*(r+1) > w:
                break r loop

            for k in [0:j-i]:
                # compare term to term and break at first difference
                if S[i+k] != S[i+r*j+k]:
                    break r loop

        if r > 1:
            # compress
            replace S[i:i+j*(r+1)] with ( S[i:i+j] )^r
            # don't forget to record end bracket...
            # and reduce w for the i-run, carrying on the j-loop for eventual smaller periods. 
            w = j-i

ฉันจงใจให้รายละเอียดเล็ก ๆ น้อย ๆ เกี่ยวกับ "วงเล็บปิดท้าย" เนื่องจากต้องการขั้นตอนมากมายในการสแต็กและคลายสต็อกซึ่งจะทำให้วิธีการหลักไม่ชัดเจน ความคิดคือการทดสอบการหดตัวต่อไปในที่สุดในคนแรก สำหรับตัวอย่าง ABCBCABCBC => (ABCBC) ² => (A (BC) ²) ²

ดังนั้นประเด็นหลักคือการหาช่วงเวลาที่มีขนาดใหญ่ก่อน โปรดทราบว่า S [i] เป็นคำที่ ith ของ S ที่ข้าม "(", ")" หรืออำนาจใด ๆ

  • i-loop คือ O (n)
  • j-loop คือ O (n)
  • r + k-loops คือ O (log (n)) ในขณะที่มันหยุดที่ความแตกต่างแรก

นี่คือ O ทั่วโลก (n²log (n))


ฉันยังไม่ชัดเจนว่า r และ k ลูปเป็น O (log n) - แยกกัน อะไรทำให้มั่นใจได้ว่าจะพบความแตกต่างหลังจากทำซ้ำมากที่สุดใน O (log n)?
j_random_hacker

ฉันเข้าใจถูกต้องหรือไม่ว่าคุณกำลังบีบอย่างตะกละตะกลาม? เนื่องจากไม่ถูกต้องให้พิจารณาเช่น ABABCCCABCCC ซึ่งคุณควรแยกตัวประกอบเป็น AB (ABC ^ 3) ^ 2
Timon Knigge

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