이것은 1986 년에 약간의 공명을 가지고 고전적인 문제 도널드 크 누스가 빠른 솔루션 구현 더그 위권에 드는 맥 킬로, 유닉스 파이프의 대부가하는으로 대응하면서, 자신의 글을 읽고 프로그래밍 기술을 설명하기 위해 8 페이지에 걸친 프로그램에 해시 시도와를 한 줄짜리, 그것은 빠르지는 않았지만 일을 마쳤습니다.
tr -cs A-Za-z '\n' | tr A-Z a-z | sort | uniq -c | sort -rn | sed 10q
물론, McIlroy의 솔루션은 시간 복잡도 O (N log N)를 가지며, 여기서 N은 총 단어 수입니다. 훨씬 빠른 솔루션이 있습니다. 예를 들면 다음과 같습니다.
다음 은 상한 시간 복잡도 O ((N + k) log k), 일반적으로 거의 선형 인 C ++ 구현입니다.
다음은 시간 복잡도 O (N + k log Q)의 해시 사전 및 힙을 사용하는 빠른 Python 구현입니다. 여기서 Q는 여러 고유 단어입니다.
import collections, re, sys
filename = sys.argv[1]
k = int(sys.argv[2]) if len(sys.argv)>2 else 10
text = open(filename).read()
counts = collections.Counter(re.findall('[a-z]+', text.lower()))
for i, w in counts.most_common(k):
print(i, w)
CPU 시간 비교 (초) :
bible32 bible256
C++ (prefix tree + heap) 5.659 44.730
Python (Counter) 10.314 100.487
Sheharyar (AWK + sort) 30.864 251.301
McIlroy (tr + sort + uniq) 60.531 690.906
노트:
- bible32는 성경 자체와 32 배 (135MB), bible256 – 256 배 (1.1GB)로 연결되어 있습니다.
- 파이썬 스크립트의 비선형 감속은 순수한 메모리에서 파일을 완전히 처리하기 때문에 발생합니다. 따라서 대용량 파일의 경우 오버 헤드가 커지고 있습니다.
- 힙을 구성하고 힙 맨 위에서 n 개의 요소를 선택할 수있는 Unix 도구가있는 경우 AWK 솔루션은 거의 선형적인 시간 복잡성을 달성 할 수 있지만 현재는 O (N + Q log Q)입니다.