2009-07-15 22 views
6

Tôi đang viết một ứng dụng cần đọc danh sách chuỗi từ tệp, lưu chúng trong cấu trúc dữ liệu và sau đó tra cứu các chuỗi đó bằng các tiền tố. Danh sách các chuỗi chỉ đơn giản là một danh sách các từ trong một ngôn ngữ nhất định. Ví dụ, nếu chức năng tìm kiếm được "stup" như một tham số, nó sẽ trả về ["stupid", "stupidity", "stupor" ...]. Nó sẽ làm như vậy trong thời gian O (log (n) * m), trong đó n là kích thước của cấu trúc dữ liệu và m là số lượng kết quả và nên càng nhanh càng tốt. Mức tiêu thụ bộ nhớ không phải là một vấn đề lớn ngay bây giờ. Tôi đang viết này trong python, vì vậy nó sẽ là tuyệt vời nếu bạn có thể chỉ cho tôi một cấu trúc dữ liệu phù hợp (tốt hơn) được thực hiện trong c với wrappers python.cấu trúc dữ liệu hiệu quả nhất cho danh sách chuỗi chỉ đọc (khoảng 100.000) với tìm kiếm tiền tố nhanh

Trả lời

15

Bạn muốn có một trie.

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

Tôi đã sử dụng chúng trong các chương trình Scrabble và Boggle. Chúng hoàn hảo cho trường hợp sử dụng mà bạn mô tả (tra cứu tiền tố nhanh).

Dưới đây là một số mã mẫu để xây dựng một trie bằng Python. Đây là từ một chương trình Boggle mà tôi đã đánh với nhau vài tháng trước. Phần còn lại là một bài tập cho người đọc. Nhưng đối với tiền tố kiểm tra về cơ bản bạn cần một phương thức bắt đầu tại nút gốc (biến words), theo các chữ cái tiền tố cho các nút con liên tiếp và trả về Đúng nếu đường dẫn đó được tìm thấy và sai khác.

class Node(object): 
    def __init__(self, letter='', final=False): 
     self.letter = letter 
     self.final = final 
     self.children = {} 
    def __contains__(self, letter): 
     return letter in self.children 
    def get(self, letter): 
     return self.children[letter] 
    def add(self, letters, n=-1, index=0): 
     if n < 0: n = len(letters) 
     if index >= n: return 
     letter = letters[index] 
     if letter in self.children: 
      child = self.children[letter] 
     else: 
      child = Node(letter, index==n-1) 
      self.children[letter] = child 
     child.add(letters, n, index+1) 

def load_dictionary(path): 
    result = Node() 
    for line in open(path, 'r'): 
     word = line.strip().lower() 
     result.add(word) 
    return result 

words = load_dictionary('dictionary.txt') 
+0

tôi bị cám dỗ để viết Node.add() là một phương pháp lặp đi lặp lại: def thêm (tự, chữ cái): tiếp theo = tự n = len (chữ cái) cho chỉ mục, thư trong liệt kê (chữ cái): nếu không (thư ở next.children): next.children [letter] = Node (chữ cái, chỉ số == n-1) next = next.children [ letter] – hughdbrown

+0

Nhưng hãy thử tưởng tượng rằng với thụt lề và dòng chính xác nghỉ giải lao. – hughdbrown

+0

Cũng thấy "DAWG", là một bộ ba sử dụng ít bộ nhớ hơn. Nhưng nó phức tạp để xây dựng (ít nhất là so với một trie). – Fantius

2

trie (or prefix tree) âm thanh ngay lên hẻm của bạn. Nó có thể thực hiện tìm kiếm trên một chuỗi tiền tố có chiều dài m trong O (m) tôi tin.

-1

mảng chuỗi.

tìm kiếm sau đó nhị phân thông qua nó để tìm kiếm trận đấu đầu tiên sau đó bước từng người một qua nó cho tất cả các trận đấu tiếp theo

danh sách

(i ban đầu đã liên kết ở đây quá ... nhưng tất nhiên điều này không có ngẫu nhiên truy cập vì vậy đây là 'bs' (mà có lẽ giải thích lý do tại sao tôi đã downvoted) tìm kiếm nhị phân của tôi vẫn là con đường nhanh nhất để đi mặc dù

+0

Thần của tôi, cho anh chàng nghỉ ngơi. – moo

+0

rất nhiều downvotes, và không ai quan tâm để giải thích tại sao? Có vẻ như mọi người chỉ đang chất đống. Câu trả lời này thỏa mãn tất cả các ràng buộc mà người dùng ban đầu được yêu cầu và đơn giản hơn để hiểu và duy trì. –

+0

@reinier - Tôi tưởng tượng bạn đã bị downvoted vì danh sách được liên kết không tốt cho việc truy cập ngẫu nhiên, do đó thời gian tìm kiếm của bạn là tuyến tính trong số phần tử. Một mảng sẽ được nhanh chóng (ish) nếu nó đã được sắp xếp, nhưng nó sẽ là O (log n), trong khi một trie là O (m), trong đó m là độ dài của tiền tố. –

Các vấn đề liên quan