Nejdelší běžný problém s podřetězcem - Longest common substring problem
v počítačová věda, nejdelší běžný problém s podřetězcem je najít nejdelší tětiva (nebo řetězce), což je a podřetězec (nebo jsou podřetězce) dvou nebo více řetězců.
Příklad
Nejdelší běžný podřetězec řetězců „ABABC“, „BABCA“ a „ABCBA“ je řetězec „ABC“ o délce 3. Další běžné podřetězce jsou „A“, „AB“, „B“, „BA“, „BC“ a „C“.
ABABC ||| BABCA ||| ABCBA
Definice problému
Vzhledem k tomu, dva řetězce, délky a délky , najděte nejdelší řetězec, který je podřetězcem obou a .
Zobecněním je k-společný dílčí problém. Vzhledem k sadě řetězců , kde a . Najít pro každého , nejdelší řetězce, které se vyskytují jako podřetězce alespoň struny.
Algoritmy
Lze najít délky a počáteční pozice nejdelších běžných podřetězců a v čas pomocí a generalizovaný příponový strom. Najít je dynamické programování náklady . Řešení zobecněného problému trvá prostor a ·...· čas s dynamické programování a vzít čas s generalizovaný příponový strom.
Příponový strom
Nejdelší běžné podřetězce sady řetězců lze najít sestavením a generalizovaný příponový strom pro řetězce a poté najít nejhlubší vnitřní uzly, které mají listové uzly ze všech řetězců v podstromu pod ním. Na obrázku vpravo je strom přípon pro řetězce „ABAB“, „BABA“ a „ABBA“, vyplněné jedinečnými zakončovacími řetězci, které se stanou „ABAB $ 0“, „BABA $ 1“ a „ABBA $ 2“. Všechny uzly představující „A“, „B“, „AB“ a „BA“ mají potomky všech řetězců s čísly 0, 1 a 2.
Vytvoření stromu přípon trvá čas (pokud je velikost abecedy konstantní). Pokud je strom procházen zdola nahoru bitovým vektorem, který říká, které řetězce jsou vidět pod každým uzlem, lze problém k-společný podřetězec vyřešit v čas. Pokud je strom přípon připraven na konstantní čas nejnižší společný předek vyhledávání, to lze vyřešit v čas.[1]
Pseudo kód
Následující pseudokód najde sadu nejdelších běžných podřetězců mezi dvěma řetězci s dynamickým programováním:
funkce LCSubstr (S [l..r], T [l..n]) L: = pole(1..r, 1..n) z: = 0 ret: = {} pro i: = 1..r pro j: = 1..n -li S [i] = T [j] -li i = 1 nebo j = 1 L [i, j]: = 1 jiný L [i, j]: = L [i - 1, j - 1] + 1 -li L [i, j]> z z: = L [i, j] ret: = {S [i - z + 1..i]} jiný -li L [i, j] = z ret: = ret ∪ {S [i - z + 1..i]} jiný L [i, j]: = 0 vrátit se ret
Tento algoritmus běží čas. Proměnná z
se používá k uchování délky dosud nejdelšího běžného podřetězce. Sada ret
se používá k držení sady řetězců, které jsou dlouhé z
. Sada ret
lze efektivně uložit pouhým uložením indexu i
, což je poslední znak nejdelšího běžného podřetězce (o velikosti z) místo S [i-z + 1..i]
. Tedy všechny nejdelší běžné podřetězce budou pro každé i in ret
, S [(ret [i] -z) .. (ret [i])]
.
Následující triky lze použít ke snížení využití paměti implementace:
- Ponechejte pouze poslední a aktuální řádek tabulky DP, abyste ušetřili paměť ( namísto )
- V řádcích ukládejte pouze nenulové hodnoty. To lze provést pomocí hash tabulek místo polí. To je užitečné pro velké abecedy.
Viz také
- Deduplikace dat
- Nejdelší palindromický podřetězec
- n-gram, všechny možné podřetězce délky n které jsou obsaženy v řetězci
- Detekce plagiátorství
Reference
- ^ Gusfield, Dan (1999) [1997]. Algoritmy řetězců, stromů a sekvencí: Počítačová věda a výpočetní biologie. USA: Cambridge University Press. ISBN 0-521-58519-8.
externí odkazy
- Slovník algoritmů a datových struktur: nejdelší běžný podřetězec
- Perl / XS implementace algoritmu dynamického programování
- Perl / XS implementace algoritmu stromu přípon
- Dynamické implementace programování v různých jazycích na wikibookech
- pracovní implementace AS3 dynamického programovacího algoritmu
- Implementace C na bázi Suffix Tree nejdelšího společného podřetězce pro dva řetězce