Znajdowanie najdłuższego powtarzającego się podsekwencji


9

Biorąc pod uwagę ciąg s, Chciałbym znaleźć najdłuższą powtarzającą się (przynajmniej dwukrotnie) podsekwencję. To znaczy, chciałbym znaleźć ciągw który jest podciągiem (nie musi być ciągły) z s takie, że w=w′⋅w′. To jest,wto ciąg, którego połówki pojawiają się dwa razy z rzędu. Zauważ, żew jest podsekwencją s, ale niekoniecznie podłańcuch.

Przykłady:

W przypadku „ababccabdc” będzie to „abcabc”, ponieważ „abc” = „abc” i „abc” pojawia się (przynajmniej) dwa razy w „ababccabdc”.

W przypadku „addbacddabcd” jedną z opcji jest „dddd”, ponieważ „dd” pojawia się dwukrotnie (nie mogę użyć tej samej litery kilka razy, ale tutaj mam 4 'd, więc jest w porządku), ale ma siłę 4. Mogę znaleźć lepszą o długości 8: „abcdabcd”, ponieważ „abcd” jest podciągiem „addbacddabcd”, który pojawia się dwukrotnie.

Jestem zainteresowany znalezieniem najdłuższego powtarzającego się podciągu. Nazywa się to również „znajdowaniem najdłuższego / największego kwadratu”, ale przeczytałem wiele artykułów, w których kwadrat jest zdefiniowany dla podłańcucha, a nie podsekwencji.

Mogę łatwo użyć algorytmu brutalnej siły, który zajmie O(n3) poprzez iterację wszystkich opcji punktu przerwania w ciągu, a następnie będę mieć dwa ciągi, w których będę szukał największej / najdłuższej wspólnej podsekwencji, ale każde sprawdzenie zajmie O(n2) za pomocą techniki programowania dynamicznego, więc cały czas będzie O(n3). Znalazłem bardziej wydajny algorytm dla najdłuższego wspólnego podciągu, który zajmujeO(n2log⁡n) , więc będzie czas pracy O(n3log⁡n).

Szukam bardziej wydajnego algorytmu dla najdłuższego powtarzającego się problemu z podsekwencją. Być może mój pomysł iteracji po wszystkich punktach przerwania marnuje zbyt dużo czasu i może zostać zredukowany do mniejszej liczby iteracji. A może algorytm o innym podejściu może rozwiązać ten problem.

Szukałem w wielu czasopismach i poprzednich pytaniach, a większość wyników, które znalazłem, dotyczyły podciągów, a nie podsekwencji.

Czytałem również, że można to zrobić za pomocą drzewek sufiksów, ale to również dotyczyło podłańcuchów i nie jestem pewien, czy taki pomysł można rozszerzyć na podsekwencje.

Szukam rozwiązania, które działa na czas O(n2). Jeśli istnieje jeden na czasO(n⋅log⁡n) będzie jeszcze lepiej (nie jestem pewien, czy takie istnieje).


4
Wyszukaj drzewa przyrostków lub tablice przyrostków.
— pseudonim

1
Jest bardzo mało prawdopodobne, że o(n2)dla tego problemu istnieje algorytm czasu, ponieważ gdyby tak się stało, można go użyć do pokonania najbardziej znanego algorytmu znajdowania LCS o dwóch długościachn smyczki u i v w następujący sposób: Utwórz ciąg xuxv, gdzie x jest n+1kopie znaku $, który nie pojawia się w żadnym z nichu lub v, a następnie uruchom swój o(n2)algorytm czasu na nim. Obie „połówki” najdłuższego powtarzającego się podsekwencji na pewno się zacznąx, więc połowa pochodzi z każdego z nich u i v, rozwiązując problem LCS.
— j_random_hacker

@j_random_hacker LCS można rozwiązać O(n+m) używając drzewa sufiksów lub w O(nlog⁡n)za pomocą skrótów.
— Zły

@Evil: Nie wiem jeszcze, jak mógłbyś podać trochę więcej szczegółów? (Czy na pewno nie myślisz o najdłuższym wspólnym łańcuchu podrzędnym , który można rozwiązać w tych zawiłościach czasowych?)
— j_random_hacker

@j_random_hacker Myślałem, że porównujesz cel o(n2)z LCS (kolejne), ale tutaj, jak wspomniałeś, tak, nawet nie widziałem działającego rozwiązania w n ^ 2 dla najdłuższej wspólnej sekwencji (znalazłem jeden dynamiczny kod programowania, propagowany na wielu stronach, który jest wadliwy, podobny do negatywnej odpowiedzi). Przepraszam, po prostu źle zrozumiałem twój komentarz.
— Zły

Odpowiedzi:


-1

Oto rozwiązanie do programowania dynamicznego.

Załóżmy, że ciąg wejściowy to x1…xn. Utwórz tabelęT których wiersze i kolumny są indeksowane 0,…,n (gdzie n jest długością ciągu), wypełnianą przez regułę

T[i,j]={0if i=0 or j=0,T[i−1,j−1]+1if xi=xj and i≠j,max(T[i−1,j],T[i,j−1])otherwise.
Odpowiedź brzmi .T[n,n]

Załóżmy, że mamy jakieś z , a warunek w Twojej instrukcji jest prawdziwy. Następnie zakłada, że postać w pozycji jest częścią obu podciągów. i,ji=j+1ifdp[i][j] = dp[i - 1][j - 1] + 1i−1=j
— j_random_hacker

3
Witamy w informatyce! Pozbądź się kodu źródłowego i zastąp go pomysłami, pseudo kodem i argumentami poprawności. Zobacz tutaj i tutaj, aby uzyskać powiązane dyskusje na temat meta.
— Raphael

@Raphael Formuła rekurencyjna nie jest liczona jako kod źródłowy.
— Number945

1
@BreakingBenjamin W zależności od wybranego języka możesz zapisać dane powtórzenie mniej więcej dosłownie. Chodzi o to, że nie ma tutaj żadnego wyjaśnienia.
— Raphael
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.