З огляду на п рядків, чи є одна з них підрядком іншої?


9

Припустимо, нам колекцію з рядків, . Я хотів би знати, чи будь-який з цих рядків є підрядком будь-якого іншого рядка в колекції. Іншими словами, я хотів би створити алгоритм для наступного завдання:nS1,,Sn

Введення:S1,,Sn

Вихід: такий, що є підрядком і , або None, якщо таких існуєi,jSiSjiji,j

Чи існує ефективний алгоритм для цього?

Якщо замінити "підрядку" на "префікс", існує ефективний алгоритм (сортуйте рядки, потім зробіть лінійне сканування для порівняння сусідніх рядків; сортування забезпечить, щоб підрядки були суміжними). Але здається, складніше перевірити, чи будь-яка рядок є підрядком будь-якої іншої рядки. Наївний алгоритм полягає в перегляді всіх пар , але для цього потрібні тести підрядкових тестів . Чи є більш ефективний алгоритм?i,jΘ(n2)

Я думаю, що ми могли б назвати це "тестування підрядків на всі пари", або щось подібне.

Моя кінцева мета - обрізати колекцію, щоб жодна рядок не була підрядком будь-якої іншої, видаляючи кожну, яка є підрядкою чогось іншого в колекції.


Підказка: Суфіксний масив.
Псевдонім

Як бічна примітка, є невірним, якщо ви видаляєте підрядки під час їх знаходження. Це буде менше. Крім того, слід сортувати за довжиною, оскільки довший рядок не може відображатися у коротшій строці. Знову тут помиляється. Θ(n2)Θ(n2)
Алексіс Вілке

@AlexisWilke, правильна: це кількість тестів підрядків у гіршому випадку (найгірший випадок, коли жодна рядок не є підрядкою жодної іншої). Сортування за довжиною дає лише два коефіцієнти, що не впливає на асимптотику. Θ(n2)
DW

Відповіді:


6

Ви можете побудувати дерево суфіксів за лінійним часом і перевірити, чи є внутрішній вузол, який відповідає повному рядку (постійний час на вузол).

Більш детально, припустимо, нам даються рядки .s1,,snΣ

  1. Побудувати (узагальнений) суфікс дерево з з попарно різних кінцевих маркерів .s1$1,s2$2,,sn$nn$1,,$nΣ

    Використовуючи алгоритм Укконена , це можна зробити в лінійний час; лінійна в сумі всіх довжин рядків.

  2. Якщо припустити, що ви позначите листя на якщо вони представляють суфікс з , дерево та знайдіть ті листків із позначкою , тобто листя, які відповідають повним струни.(i,j)si[j..|si|]sin(i,0)

    Для цього потрібен лінійний час у розмірі дерева, який сам по собі є лінійним у розмірі введення.

  3. Листки нащадків батьківського зразка (до якого доходить край, позначений ), представляють усі збіги з набору; це випливає з основного інваріанта суфіксних дерев. Знайдіть будь-яку відповідність, опустившись до будь-якого аркуша (але ).(i,0)$i(i,0)

    Це знову потребує лінійного часу.

Виразні кінцеві маркери насправді не потрібні; одного, який використовується для завершення всіх рядків, цілком достатньо, якщо ви дозволяєте кілька міток на аркуш.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.