이러한 문자열 연산을 지원하는 '문자열 스택'데이터 구조가 있습니까?


28

다음 작업을 수행 할 수 있는 문자 집합 위에 문자열 집합을 저장하는 데이터 구조를 찾고 있습니다. 우리 나타내고 문자열 집합 데이터 저장 구조로서 .ΣD(S)S

  • Add-Prefix-Set에 : 일부 설정 주어진 크기 상수에 의해 제한되고, 그 문자열의 길이 상수에 의해 제한되는 문자열 (비어)의, 반환 . 이 경계 상수는 모두 전역입니다. 모든 입력 대해 동일합니다 .D(S)TD({ts | tT,sS})T
  • Get-Prefixes에 : 리턴 입니다. 시간에 내용을 열거 할 수 있다면이 세트에 어떤 구조가 사용되는지는 신경 쓰지 않습니다 .D(S){a | asS,aΣ}O(|Σ|)
  • Remove-Prefixes에 : 리턴 .D(S)D({s | asS,aΣ})
  • Merge: 및 이면 반환하십시오 .D(S)D(T)D(ST)

이제 시간 에 모든 작업을 수행하고 싶지만 시간 에 모든 작업을 수행하는 구조는 괜찮습니다. 여기서 은 가장 긴 문자열의 길이입니다. 구조. 병합의 경우에, I는 원하는 실행 시간, 있다 처음과 번째 구조를.O(1)o(n)no(n1+n2)n1nn2n

추가 요구 사항은 구조가 변경 불가능하거나 적어도 위의 작업이 '새로운'구조를 반환하여 이전 구조에 대한 포인터가 여전히 이전과 같이 작동해야한다는 것입니다.

할부 상환에 대한 참고 사항 : 괜찮습니다. 그러나 지속성을 조심해야합니다. 항상 오래된 구조를 재사용 할 때 같은 구조에서 특정 작업 집합으로 최악의 경우를 겪으면 문제가 생길 수 있습니다 (따라서 생성하는 새 구조는 무시).

작업중 인 파싱 알고리즘에서 이러한 구조를 사용하고 싶습니다. 위의 구조는 알고리즘에 필요한 미리보기를 유지합니다.

나는 이미 trie 사용을 고려 했지만 주요 문제는 효율적으로 병합하는 방법을 모른다는 것입니다. 문자열 집합이 Add-Prefix-Set단일 문자 문자열로만 구성된 경우 이러한 집합을 스택에 저장 하면 처음 세 작업의 실행 시간 이 제공 됩니다. 그러나이 방법은 병합에도 효과가 없습니다.O(1)

마지막으로, 요인 관심이 없습니다. : 이것은 내가 돌보는 모든 것에 대해 일정합니다.|Σ|


문자열은 오퍼레이션에 의해서만 구성 Add-Prefix-Set되거나 임의의 문자열 세트로 시작합니까?
Joe

2
병합 조작 전에 와 모두 에 길이 의 문자열이 있다고 가정하십시오 . 이 문자열이 시간에 중복되는지 여부를 어떻게 감지 할 수 있습니까? n1=n2STo(n1+n2)
Joe

하나의 단일 문자 문자열로 시작하는 세트로 시작하지만 빈 문자열도 괜찮습니다 (그냥 할 수 있습니다 Add-Prefix-Set)
Alex ten Brink

@ 조 : 그것은 좋은 질문입니다-병합 작업이 그런 구조를 얻을 가능성을 거의 깰 것이라고 확신하기 시작하고 있습니다 ...
Alex ten Brink

"세트 스택"표현을 사용하면 최소 2 개의 스택(n1,n2)
Joe

답변:


5

나는 꽤 오랫동안 생각했지만 trie와 같은 DAG 구조에서 가장 어리석은 방법으로 모든 작업을 수행하는 데 문제가 없었습니다.

추가 접두사 세트

에서 문자열 트리를 만듭니다 . 각 리프 노드를 이전 트라이의 루트에 연결하십시오.T

복잡성 :O(|T|)

병합

두 구조의 뿌리를 결합하십시오 : 첫 번째 노드의 두 번째 루트 자식의 모든 자식 노드를 만드십시오. 이제 동일한 노드에서 같은 문자로 표시된 여러 모서리가있을 수 있습니다.

복잡성 :O(1)

루트의 게으른 업데이트

  1. 각 문자에 대해이 문자로 표시된 모서리로 액세스 가능한 루트의 모든 하위 항목을 통합하십시오. ( + 추가 된 각 모서리에 대한 상각 )O(|Σ|)O(1)
  2. 상단에서 루트로 들어가는 모든 모서리를 삭제하십시오. (제거 접두사 후에 발생할 수 있으며 추가 된 각 가장자리에 대해 상각 됩니다)O(1)

Get-prefixes

루트를 느리게 업데이트하십시오. 이제 뿌리의 모든 자식을 찾아서 가장자리에있는 글자 세트를보고하십시오.

복잡성 :O(|Σ|)

접두사 제거

루트를 느리게 업데이트하십시오. 루트의 모든 자식을 하나로 묶고이 포인터의 결과에 루트 포인터를 설정하십시오. 새 루트를 느리게 업데이트하십시오.

복잡성 : + 지연 업데이트O(|Σ|)

고집

이 데이터 구조에 대한 모든 정보 는 노드 당 정보와 노드의 각 하위에 대한 정보 와 함께 배열로 저장할 수 있습니다 . 각 작업은 이러한 배열에서 할당 세트로 유지 될 수 있습니다. 영속 범위 트리 또는 영속 배열로 볼 수있는 다른 데이터 구조를 사용하십시오. 메모리 및 공간 복잡성을위한 추가 승수 . 여기서 은 모든 쿼리의 총 문자 수입니다.O(1)O(|Σ|)O(logN)N

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.