2010-07-28 2 views
3

나는이 목록에서 자주 검색 할 수있는 정렬 된 목록 (사전 - 100,000 단어)과 많은 단어가 있습니다. 따라서 성능이 문제입니다. HashSet.contains (theWord) 또는 Collections.binarySearch (sortedList, theWord)는 매우 빠르다는 것을 알고 있습니다. 그러나 나는 실제로 전체 단어를 찾고 있지 않습니다.startsWith()와 같은 빠른 문자열 검색 equals()

내가 원하는 것은 "se"를 검색하고 모든 단어를 "se"로 시작한다고 가정 해 보겠습니다. Java 나 라이브러리에서 사용할 수있는 솔루션이 있습니까?

더 나은 예 : 정렬 된 목록에서

myWordList.subList ("AB"의 간격을 반환 // 다음 조작

List.subList (문자열 beginIndex의, 문자열에서 endIndex)에 대한 빠른 솔루션, "기원전");

참고 : 여기는 매우 비슷한 질문이지만 허용 된 대답은 만족스럽지 않습니다. Overriding HashSet's Contains Method

답변

9

당신이 여기에서 찾고있는 것은 데이터 구조가 commanly에 '트라이을'이라는 것입니다 문자열의 첫 번째 문자, 두 번째 문자, 두 번째 문자 등입니다. 결과는 매우 큰 문자열 집합의 하위 집합을 매우 빠르게 접두어로 추출 할 수있게합니다.

+0

인기있는 라이브러리에서 제공하는 구현이 있습니까? –

+0

이 사람? 그것이 아파치 코 몬즈 컬렉션과 구글 콜렉션에 기여했다고 주장하지만, ACC에 대한 간략한 설명은 Javadoc에서 나타나지 않았다. http://code.google.com/p/patricia-trie/ –

+0

예. 정확히 내가 물어 보지 못한 이유입니다. –

2

Trie 구조는 사전과 공통 접두어가있는 단어를 찾기에 매우 적합합니다. Google Collections/Guava에는 의 기고 물이 있습니다.

http://en.wikipedia.org/wiki/Trie

그것은 나무의 첫 번째 레벨이 포함되어 접두사에 의해 색인 나무에 문자열을 저장합니다

+0

나는 그것을 조사했다. 괜찮아 보인다. 그러나 코드를 컴파일 할 수 없습니다. 그것은 다른 것을 복잡하게 만드는 다른 꾸러미들에게 방해가됩니다. 문자열에서 이진 검색 구현을 수정합니다. – hrzafer

+0

Guava 라이브러리 또는 Apache commons 컬렉션 내에서 Trie 구현을 파악할 수 없습니다. 다른 이름 밑인가? –

2

새로운 구조는별로 필요하지 않습니다. 문제는 목록에서 이진 검색으로 해결할 수 있습니다. 특히 이진 검색을 수정하여 첫 번째 요소 (지정된 접두어가있는 첫 번째 요소)를 반환 할 수 있습니다.

List.subList (문자열 beginIndex의, 문자열에서 endIndex는) // 내가 바보가 될 수있다
간격을 반환하지만 인덱스 어떤 종류의 문자열 유형이? 이 부분을 명확히 할 수 있습니까?

+0

난 그냥 List.subList (int beginIndex, int endIndex) – hrzafer

+0

@hrzafer와 같은 알려진 방법의 측면에서 문제를 설명하고 싶었어요 그럼, 그 매개 변수는 무엇을 의미합니까? 문자열 접두사와 접미사입니까? –

+0

예, 문자열 접두사입니다. – hrzafer

1

검색 결과는 주문한 단어 목록의 범위가됩니다. 이를 얻으려면 범위의 첫 번째 요소와 마지막 요소의 색인이 필요합니다.

첫 번째 검색을 수행하려면 원래 검색 문자열 ("se")을 사용하여 이진 검색을 실행하고 각 반복의 현재 위치와 비교하십시오. 현재 위치의 단어가 검색 문자열보다 크지 만 현재 단어가 더 낮 으면 중지하십시오.

마지막 색인을 얻으려면 검색어 "+"z "("sez ")에서 다른 이진 검색을 실행하십시오. 그러나 현재 색인의 단어가"sez "보다 작지만 현재 +1이 더 큰 경우에만 중지하십시오 .

마지막으로 프로그래밍 언어에서 사용할 수있는 모든 방법으로 첫 번째 및 마지막 색인으로 표시된 범위를 반환하십시오.

이 방법은 두 가지 가정에 구축된다

  • 문자열 비교는 "B"를보고 'AZ'보다
  • "Z"는 단어의 목록 중 가장 숯 값

이 알고리즘은 JavaScript 데이터 조작 라이브러리 (jOrder.net)에 구현되어 있습니다.

+0

"z"가 아닌 Character.MAX_VALUE를 사용해야합니다.하지만이 외에도이 게시물은 꽤 많이 요약되어 있습니다. 당신이하고있는 일에 따라, 내가 보통 접두어에 이진 검색을하는 것과 같은 문제가 생겼을 때, "while (value.get (x) .startsWith (접두어))"를 사용하여 처리하는 대신에 범위를 돌려줍니다. – Jay

+0

나는 Character.MAX_VALUE 부분에 완전히 동의하지만, 100k 크기가 주어지면, K (K = 결과 세트 길이)가 아닌 log (N) (N = 사전 길이) 추가 문자열 비교를 수행하는 것을 고려하는 것이 낫지 않습니까? ? –