잠시 동안 나를 괴롭힌 문제가 있습니다. 문자열 이 1과 0 의 시퀀스이고 와일드 카드 문자열 이 1, 0 및? s 의 시퀀스 라고 가정하겠습니다 . 모든 문자열과 와일드 카드 문자열의 길이는 같습니다. 이들은 표준 UNIX 와일드 카드입니다. 10 ?? 1은 10011, 10111 등과 일치합니다. 해당 위치에서 1 또는 0과 일치합니다. 경우 및 와일드 카드 문자열, 우리는 쓰기 w V \ 당량 일치 모든 문자열 경우 V가 도 일치한다 w를 .
문제 : 와일드 카드 문자열 세트 와 쿼리 (와일드 카드 문자열)가 주어지면 v \ leq w ? 와 같은 w \ in S가 있습니까? 그렇지 않은 경우 v 를 S에 효율적으로 추가 할 수 있습니까?
다음은 명백한 솔루션입니다 (여기서 는 문자열의 크기, 은 RAM의 단어 크기 (일반적으로 32 또는 64)) : 목록의 각 요소를 살펴보고 테스트하십시오. 조건 (비트 트위들 링을 사용하여 2 또는 3 작업에서 수행 할 수 있음). 또한 스캔하는 동안 가 모든 항목 를 보유 하는지 테스트하십시오 . 경우 우리의 테스트에 실패하고 추가 세트에, 그리고 제거 우리가 표시들 '.
그러나 그것은 충분히 빠르지 않습니다. 솔루션이 있거나 완벽한 세계에서 기수 트리 ( ) 와 유사한 복잡성 이 있다면 정말 멋질 것입니다 . 쿼리가 대략 정확 하다는 것도 괜찮습니다 . 즉, 인 경우 yes 또는 no를 반환합니다. 그러나 조건이 확실하지 않으면 no를 반환하십시오.
이것이 최악의 경우에 도움이되지는 않지만 S의 모든 요소 가 와일드 카드 문자열로 묶여 있다고 가정 할 수 있습니다 . 즉, 모든 w \ in S 에 대해 v \ geq w 와 같은 v 가 있습니다 .
내가 시도한 아이디어
- 와일드 카드 문자열은 결합-실 밀화를 형성합니다. 와일드 카드 문자열을 포함하는 n-ary 트리를 가질 수 있습니다. 나뭇잎은 와일드 카드 문자열이되고 가지는 모든 어린이의 조인을 나타냅니다. 쿼리와 조인을 비교할 수없는 경우 해당 지점의 모든 자식과 비교하려고 시간을 낭비하지 않아도됩니다. 또한 업데이트를 수행하고 업데이트가 조인보다 큰 경우 전체 분기를 간단히 삭제할 수 있습니다. 불행히도, 이것은 최악의 경우 여전히 이며, 요소를 추가하기 위해 트리를 스캔 할 때 항상 "최상의"조인을 찾지는 않습니다.
- 의 기수 트리를 형성 할 수 있습니다. 우리는 가 와일드 카드 문자열에 의해 묶여 있음을 알고 있습니다 . 그것이? 0? 0이라고 가정하십시오. 그런 다음 trie의 모든 분기는 문자열의 첫 번째 비트와 세 번째 비트에만 있어야합니다. 쿼리에서 분기하는 현재 비트가 1이면? 그리고 1 개의 가지; 0이면?를 확인합니다. 그리고 0 가지; 그것이?라면, 우리는? 분기. 우리는 잠재적으로 여러 개의 브랜치를 가져야하기 때문에 그리 좋아 보이지 않습니다 (같은 이유로 트라이를 업데이트하기는 어렵습니다). 매칭은 매우 빠른 작업이므로 트리에서 많은 순회를 수행하는 순진한 전략과 비교할 때 아프다 (포인터를 따르는 것이 일부 OR 및 AND를 수행하는 것보다 훨씬 비쌉니다).
관련된 일
네트워킹 커뮤니티에서이 문제는 "패킷 분류"로 나타납니다. 여기에는 알려진 알고리즘 및 데이터 구조에 대한 훌륭한 조사가 있습니다 . 불행하게도, 와일드 카드 문자열은 접두사 만 일치한다고 가정하고 쿼리는 이러한 문자열의 튜플입니다. 물론 일반적인 와일드 카드 문자열을 다음 기준에 맞게 변환 할 수 있습니다. 1? 00? 1 ?? (1, β, 0, 0, β, 1, β, β)이다. 그러나 이것은 효율적이지 않습니다. 다른 가정은 이러한 튜플이 "색상"과 연관되어 있고 쿼리는 색상이 일치하는 것만이 아니라 색상을 반환해야한다는 것입니다. 이것은 튜플을 주문해야하기 때문에 (또는 (0,?) 및 (?, 1) 중 어느 것이 (0, 1)과 일치하는지 모호하기 때문에) 문제를 훨씬 더 어렵게 만듭니다.
알고리즘 커뮤니티에서 "무관심"과 일치하는 하위 문자열을 찾는 것과 관련된 많은 결과를 발견했습니다. 이것은 상당히 어려운 문제이며 실제로 어떤 기법도 사용할 수 없습니다.
결론적으로
도움을 주셔서 감사합니다!