Для цієї проблеми можна використовувати масиви суфіксів . Вони містять вихідні положення кожного суфікса рядка, відсортованого в лексикографічному порядку. Незважаючи на те, що вони можуть бути побудовані по наївності в складності, є методи , щоб побудувати їх в thetas ; ( п ) складності. Дивіться, наприклад, це і це . Назвемо цей масив суфіксів SA.O ( n журналn )Θ ( n )
Після створення суфіксного масиву нам потрібно побудувати найдовший масив загального префікса (LCP) для масиву суфіксів. Масив LCP зберігає довжину найдовшого загального префікса між двома послідовними префіксами в масиві суфіксів (лексикографічні послідовні суфікси). Таким чином, LCP [i] містить довжину найдовшого загального префікса між SA [i] та SA [i + 1]. Цей масив також може бути побудований у лінійному часі: дивіться тут , тут і тут кілька хороших посилань.
Тепер, щоб обчислити довжину найдовшого префікса, спільного для будь-яких двох суфіксів у дереві суфіксів (замість послідовних суфіксів), нам потрібно використовувати деяку структуру даних RMQ . У наведених вище посиланнях було показано (і їх можна легко побачити, якщо масив візуалізується як суфіксне дерево), що довжина найдовшого загального префікса між двома суфіксами, що мають позиції і v ( u < v ) у масиві суфіксів , може бути отримано як m i n u < = k < = v - 1 L C P [ k ]уvu < vм я нu < = k < = v - 1L CП[ k ]. Хороший RMQ може попередньо обробити масив за час O ( n ) або O ( n log n ) та відповісти на запити форми L C P [ u , v ] в O ( 1 ) час. Дивіться тут про алгоритм стислих RMQ, а тут - хороший підручник з питань RMQ та взаємозв'язку (та скорочень) між LCA та RMQ. Це ще один приємний альтернативний підхід.L CПO ( n )O ( n журналn )L CП[ u , v ]O ( 1 )
За допомогою цієї інформації ми будуємо суфіксний масив та пов’язані з ними масиви (як описано вище) для конкатенації двох рядків з роздільником між ними (наприклад, T # P, де "#" не зустрічається в жодному рядку). Тоді ми можемо виконати збіг рядків k невідповідності за допомогою методу "кенгуру". Це і це пояснює метод кенгуру в контексті дерев суфіксів, але він може бути безпосередньо застосований і до масивів суфіксів. Для кожного індексу тексту T знайдіть L C P суфікса T, що починається з i, і суфікса PiТL CПТiПпочинаючи з 0. Це дає місце, після якого виникає перше невідповідність при зіставленні з T [ i ] . Нехай ця довжина буде l 0 . Пропустіть невідповідний символ як у T, так і в P і спробуйте відповідати решти рядків. Тобто, знову - таки знаходимо л З Р з Т [ я + л 0 + 1 ] і Р [ л 0 + 1 ] . Повторіть це, доки не отримаєте k невідповідностей або завершення рядків. КоженПТ[ i ]л0ТПL CПТ[ i + l0+ 1 ]П[ л0+ 1 ]к є O ( 1 ) . Є O ( K ) L З Р «S для кожного індексу я з T , даючи це загальна складність O ( п до ) .LCПO ( 1 )O ( k ) LCПiТO ( n k )
Я використав простіший для реалізації RMQ, що дає загальну складність , або O ( n k + n log n ), якщо m = O ( n ) , але це можна також виконати в O ( n k ), як описано вище. Для цієї проблеми можуть бути й інші прямі методи, але це потужний і загальний підхід, який можна застосувати до багатьох подібних проблем.O ( n k + ( n + m )log( n + m ) )O ( n k + nlogn )m = O ( n )O ( n k )