2010-08-04 3 views
5

저는 C++의 초보자입니다. C++에서 모든 단어를 사전에 저장하고 사전에 단어가 있는지 찾아내는 데 가장 적합한 데이터 구조를 말해 줄 수 있습니까? 나는 해쉬 테이블이 최고라는 것을 알고 있지만 어떤 데이터 구조가 그들을 사용하는지 모른다.C++의 최상위 데이터 구조로 사전에서 문자열 찾기

대단히 감사합니다.

+0

지도, 세트 등과 같이 표준 라이브러리에서 제공하는 C++ DS가 있으므로 문자열을 검색하는 데 가장 적합한 DS입니다. 나는 모든 문자열을 읽고 검색 할 것이다. – brett

답변

9

C++ 구현의 표준 라이브러리에는 unordered_set 또는 hash_set이있을 수 있습니다. 그것들은 본질적으로 같은 것이다. 전자는 앞으로 출시 될 C++ 0x 표준의 일부이며 최신 컴파일러에서 지원되며 후자는 원래 SGI STL에서 제공되며 많은 표준 라이브러리 구현에 포함됩니다.

+1

표준 라이브러리의 hash_set 또는 unordered_set 부분입니까? – brett

+0

@brett :'hash_set' : 공식적으로? 아니요. 그러나 많은 표준 라이브러리 구현 (Visual C++ 및 libstdC++ 포함)에는이 라이브러리가 포함되어 있습니다. 'unordered_set' : 아직 없습니다. 2011 년 언젠가 C++ 0x가 승인되면 표준 라이브러리의 일부가 될 것입니다. 일부 표준 라이브러리 구현 (예 : Visual C++ 2010 라이브러리)에는이 라이브러리가 포함되어 있습니다. –

+0

내 리눅스 컴파일러에서 사용할 수 있습니까? G ++? 가장 좋은 데이터 구조는 무엇입니까? – brett

2

hash_map, C++의 컴파일러 라이브러리 (예 : GNU C++ 또는 Microsoft Visual C++)에있는 경우 컴파일러가 아닌 다른 컴파일러를 사용하고 있다면 어쨌든 hash_map의 제 3 자 구현을 찾을 수있을 것으로 생각됩니다.

앞으로 나올 C++ 표준에서는 이와 동일한 데이터 구조 std::unordered_map을 대신 호출합니다.

사전에있는 단어와 정보를 모두 연관시키지 않으려면 단어가 포함되어 있는지 여부 만 기록하면됩니다 (_map 대신) _set 변형을 사용할 수 있습니다 이름을 입력하십시오.

물론이 템플릿은 모두 (C++ 표준 라이브러리의 모든 컨테이너로) 템플릿이기 때문에 일반적인 템플릿 구문을 사용하여 적절하게 인스턴스화해야합니다.

+0

하지만 그는 단어 조합으로 더 좋을 것이라고 생각합니다. 연관 키 값 컨테이너 인지도가 아닙니다. 제임스 (James)가 말했듯이, 어떤 설정 구현으로도 충분합니다. –

+0

@Hernán, 내가 언급했듯이 그가 존재/부재 정보 만 필요로한다면'hash_set' 또는'unordered_set'만으로 충분할 것입니다. 만약 그가 보조 정보를 기록 할 필요가 있다면'... map '변종은 더 좋게 (그리고 효율적으로). –

0

단어에 대한 다른 종류의 정보 (예 : 맞춤법 검사기)가 필요없이 절대로 바뀌지 않는 사전에 단어가 포함되는지 여부를 결정하는 유일한 요구 사항은 Bloom filter이 효율적입니다 이 작업을위한 데이터 구조.

각 단어와 연결할 다른 데이터가있는 경우 std::map은 좋은 범용 시작점입니다.

자동 완성이 필요한 경우 (부분 단어를 입력 한 경우) Prefix tree (trie)을 사용할 수 있습니다.

+0

블룸 필터는 확률 론적 데이터 구조입니다. 그것은 당신에게 최종 Yes/No 응답을 줄 수는 없습니다. 거짓 긍정은 가능하지만, 잘못된 음수는 아닙니다. 그래도 trie는 좋은 생각입니다. –

4

해시는 꽤 좋지만 가장 좋은 구조는 trie입니다. GCC의 <ext/pb_ds/assoc_container.hpp>에서 트라이를 얻을 수 있습니다. the online reference을 참조하십시오. 없는 순수한 setmap -like 기능

#include <ext/pb_ds/assoc_container.hpp> 
#include <string> 
#include <iostream> 

int main() { 
     pb_ds::trie< std::string, int > dict; 

     dict.insert(std::make_pair("hello", 3)); 

     std::cerr << (dict.find("hello") != dict.end()) << std::endl; 
     std::cerr << (dict.find("goodbye") != dict.end()) << std::endl; 
} 

가 제공된다. 위의 예제에서 나는 더미 데이터를 맵에 추가하기 위해 ... int을 추가했다.

GCC 밖에서 작동하지 않는다면 어떤 상처를 입을까요? 한편

하는 - 표준 해시 테이블 (안 std:: 또는 ext:: 무엇이든) 만 대신 단어 자체의 단어의 체크섬 중 검색 즉 대략 일치를 찾을 수있다. 그것은 가장 빠르고 가장 컴팩트 한 솔루션이 될 것입니다. Bloom filters을 기반으로하는 사전에는 수 킬로바이트에 수천 단어가 포함될 수 있습니다.

+0

어떻게 GCC 밖에서 작동하지 않습니까? 이러한 라이브러리를 Visual Studio (CL 컴파일러)로 가져 오는 방법은 없습니다. –

+0

@YechielLabunskiy 파일은 단순히 GCC에 포함되어 있습니다. MSVC가 GCC 확장에 의존하지 않거나 MSVC 버그를 이동하지 않으면 MSVC에서 작동 할 수 있습니다. 확실히 한 번 사용해 볼 가치가 있습니다. 별도의 제 3 자 라이브러리로 취급하고 업데이트를 모니터링해야합니다. – Potatoswatter

0

독자적인 솔루션을 구형하고 사전이 수정되어있는 경우 perfect hash은 좋은 방법입니다. 상수 조회 시간을 보장합니다.

+0

1 년이나 2 년 전 정확한 문제 (고정 사전 생성)가 있었고 완벽한 해싱이 실제적으로 2 계층 데이터 구조를 필요로하므로 조회마다 여러 메모리 읽기가 필요하다는 사실에 실망했습니다. 그것은 체인이있는 일반 오래된 해시 테이블보다 느리게 끝납니다. –

+0

FWIW, 테이블 생성을 위해 작성한 코드는 다음과 같습니다. http://hg.mozilla.org/tracemonkey/file/e555673c8119/js/src/xpconnect/src/qsgen.py#l1488 코드 : http : //hg.mozilla.org/tracemonkey/file/e555673c8119/js/src/xpconnect/src/xpcquickstubs.cpp#l70 실제로는 3 개의 엔트리를 생성합니다 (몇 개의 룩업은 모든 체인을 걸어야합니다) . –

1

트라이를 사용하는 것이 좋습니다. Trie는 빠른 검색 및 예, 자동 완성을 사용하여 메모리 효율적인 사전을 작성하는 데 적합한 데이터 구조입니다.

해시 테이블로 생각하면 키 - 값 쌍 (또는 키 조회)을 빠르게 검색 할 수 있지만 해시 테이블과 달리 정렬 된 순서로 키를 반복 할 수 있습니다.

자세한 내용은/Trie - Wiki을 참조하십시오.