ID | LCP | str |
1 | 0 | 0 1 2 3 2 |
0 | 0 | 1 0 1 2 3 2 |
2 | 1 | 1 2 3 2 |
3 | 0 | 2 3 2 |
5 | 1 | 2 |
4 | 0 | 3 2 |
Корректируются все развилки дерева (так как они могут совпадать в первых символах):
Суффиксный массив чётного дерева исходной строки:
ID | LCP | str |
2 | 0 | 1112212221 |
0 | 1 | 121112212221 |
4 | 2 | 12212221 |
6 | 0 | 212221 |
10 | 2 | 21 |
8 | 1 | 2221 |
ID | LCP | str |
3 | 0 | 112212221 |
7 | 1 | 12221 |
11 | 1 | 1 |
1 | 0 | 21112212221 |
5 | 1 | 2212221 |
9 | 3 | 221 |
Слитое дерево (условно):
Слитое дерево (в упрощённом виде):
Для того чтобы узнать общее начало двойной дуги, мы должны взять одну чётную и одну нечётную на дереве, для которых родителем
является конец нашей двойной дуги. Например на рисунке выше двойная дуга (1), конец я пометил зелёным - является общим родителем для вершин
3 и 6. Чтобы узнать на каком расстоянии будет расслаиваться двойная дуга, надо увеличить номера вершин на еденицу
и найти их родителя, он будет находится на еденицу ближе к корню (и путь у вершин будет одинаковой строкой, не считая размера). Родителя вершин 4, 7 я пометил жёлтым, он
находится на расстоянии 1 от корня, следовательно дуга (1) должна расслаиваться в двух символах от корня, т.е. обе дуги совпадают и их просто надо слить.
Разберём дуги по порядку:
Дерево после обработки:
На разных шагах приходится применять суфф. деревья или суфф. массивы. Преобразование дерева в массив и обратно делается за линейное время.
В этих случаях можно не продолжать рекурсивные вызовы, а делать специфичное постоение, это сильно ускоряет всю работу:
Для справки покажу рекурсивную обработку файла rfc-index.xml
глубина | размер строки | число уник. пар (новый алфавит) | уникальные пары % |
1 | 7661287 | 3193 | > 1% |
2 | 3830643 | 61509 | 3% |
3 | 1915321 | 169206 | 17% |
4 | 957660 | 167675 | 35% |
5 | 478830 | 124981 | 52% |
6 | 239415 | 91360 | 76% |
7 | 119707 | 56328 | 94% |
8 | 59853 | 29900 | 99% |
9 | 29926 | 14963 | 100% (все пары уникальны) |
Если бы можно было каким-то образом узнавать совпадают ли двойные дуги полностью или нет, тогда можно было бы полностью избавиться от поиска общих предков. Потому что в случае полного совпадения дуг она полностью сливается. А в случае неполного, не обязательно знать на каком символе она будет расслаиваться. Достаточно узнать какая из двух дуг идёт раньше по алфавиту. Дерево в таком случае использовать будет не интересно, но при его обычном обходе можно получить правильный суффиксный массив, который удобно использовать на более высоком слое рекурсии или напрямую.
ID | str |
1 | 1112212221 |
3 | 112212221 |
4 | 12212221 |
0 | 121112212221 |
7 | 12221 |
1 | 21112212221 |
10 | 21 |
6 | 212221 |
9 | 221 |
5 | 2212221 |
8 | 2221 |
[тут реализация] - я выложил рассказ о практической реализации, и немного о суф. деревьях