Чи існує структура даних "стек рядків", яка підтримує ці рядкові операції?


28

Я шукаю структуру даних, яка зберігає набір рядків над набором символів , здатним виконувати наступні операції. Позначимо , в якості структури даних , що зберігає безліч рядків .D ( S ) SΣD(S)S

  • Add-Prefix-Seton : заданий деякий набір (можливо, порожніх) рядків, розмір яких обмежений постійною, а довжина рядків обмежена постійною, return . Обидва ці константи є глобальними Обмежуючими: вони однакові для всіх входів .T D ( { t s | t T , s S } ) TD(S)TD({ts | tT,sS})T
  • Get-Prefixeson : повернення . Зауважте, що я не дуже заперечую, яка структура використовується для цього набору, якщо я можу перерахувати його вміст за час .{ a | a s S , a Σ } O ( | Σ | )D(S){a | asS,aΣ}O(|Σ|)
  • Remove-Prefixeson : return .D ( { s | a s S , a Σ } )D(S)D({s | asS,aΣ})
  • Merge: задано і , повернути .D ( T ) D ( S T )D(S)D(T)D(ST)

Тепер я дуже хотів би виконати всі ці операції в час, але я добре зі структурою, яка виконує всі ці операції в час, де - довжина найдовшої рядки в будова. У випадку злиття я б хотів час роботи, де - для першої, а - для другої структури.o ( n ) n o ( n 1 + n 2 ) n 1 n n 2 nO(1)o(n)no(n1+n2)n1nn2n

Додатковою вимогою є те, що структура є непорушною або, принаймні, що вищезазначені операції повертають "нові" структури такі, що вказівники на старі все ще функціонують як раніше.

Примітка про амортизацію: це нормально, але ви повинні стежити за наполегливістю. Оскільки я повторно використовую старі структури, я буду зазнавати проблем, якщо потрапляю в гіршому випадку з деяким набором операцій над тією ж структурою (так ігноруючи нові структури, які вона створює).

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

Я вже розглядав питання про використання трійника , але головна проблема полягає в тому, що я не знаю, як ефективно об'єднати спроби. Якщо набір рядків for Add-Prefix-Setскладається з лише односимвольних рядків, то ви можете зберігати ці набори в стеку, що дасть вам час для виконання перших трьох операцій. Однак і цей підхід не працює для злиття.O(1)

Нарешті, зауважте, що мене не цікавлять фактори: це постійна для всіх, що мені цікаво.|Σ|


Чи створюються рядки тільки операцією, Add-Prefix-Setабо ви починаєте з довільного набору рядків?
Джо

2
Припустимо , що перед операцією злиття, є рядок довжини в обох і . Як ви могли визначити, чи є цей рядок дублікатом за час? S T o ( n 1 + n 2 )n1=n2STo(n1+n2)
Джо

Ви починаєте з набору, в якому є одна одночастова струна, але порожня рядок також чудова (ви можете просто в Add-Prefix-Setній)
Alex ten Brink

@Joe: це гарне запитання - я починаю переконуватись, що операція злиття в значній мірі порушує будь-який шанс отримати таку структуру ...
Алекс десять Бринк

Якщо ви використовуєте представлення "стека наборів", ви можете об'єднати два стеки в хв(n1,n2)
Джо

Відповіді:


5

Я думав досить довго, але не знайшов проблеми з виконанням усіх своїх операцій найбільш дурним можливим способом у структурі DAG, подібної до трійки:

Add-Prefix-Set

Створення синтаксичного дерева рядків з . З’єднайте кожен вузол листя з коренем старого тріє.T

Складність:O(|T|)

Злиття

Об’єднайте коріння двох структур: зробіть усі дочірні вузли другого кореневого дітей першого вузла. Тепер у вас може бути кілька країв, позначених одним і тим же символом, що йде від одного вузла.

O(1)

Ледаче оновлення кореня

  1. O(|Σ|)O(1)
  2. O(1)

Get-префікси

Ледаче оновити корінь. Тепер знайдіть усіх дітей кореня та повідомте про набір букв на краях, що йдуть до них.

O(|Σ|)

Видалити-префікси

Ледаче оновити корінь. Об'єднайте всі діти кореня та встановіть кореневий покажчик на результат цього об'єднайте. Ледачий оновлення нового кореня.

O(|Σ|)

Наполегливість

O(1)O(|Σ|)O(logN)N

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