2011-07-09 57 views
6

Thuật toán nào bạn đề xuất để tìm ra các tiền tố phổ biến nhất dài nhất trong danh sách chuỗi?Đề xuất thuật toán chuỗi để tìm tất cả tiền tố chung của danh sách các chuỗi

tôi có thể có chuỗi như:

Call Mike and schedule meeting. 
Call Lisa 
Call Adam and ask for quote. 
Implement new class for iPhone project 
Implement new class for Rails controller 
Buy groceries 

Tôi muốn tìm hiểu các tiền tố sau:

"Call " 
"Implement new class " 

tôi sẽ sử dụng Objective C, do đó, một giải pháp sẵn sàng cacao làm sẽ là một cộng (mặc dù không phải là một).

+0

Vì vậy, bạn muốn tất cả các chuỗi 's' sao cho' s' là tiền tố chung của hai chuỗi trong danh sách và 's' không phải là chuỗi con nghiêm ngặt của bất kỳ tiền tố chung nào khác của cùng hai chuỗi và 's' không phải là chuỗi rỗng? Còn về '{" a1 "," a2 "," ab1 "," ab2 "}', bạn có muốn '" a "' hay không? –

+0

Vâng, đúng vậy. Và không, tôi không cần. – cfischer

Trả lời

2

Điều đó phụ thuộc vào những gì bạn sẵn sàng xem xét tiền tố.

Tôi cho rằng câu trả lời chung là tạo Trie (có thể là cây hậu tố hậu tố) lưu trữ tất cả các chuỗi vào một cây n-ary. Xem http://en.wikipedia.org/wiki/Trie

enter image description here

Tùy thuộc vào tiêu chí của bạn cho 'prefix' (nói, n ký tự), bạn có thể chọn tất cả các nút của bậc n rằng có nhiều hơn một trẻ em.

Bạn sẽ có danh sách các tiền tố lặp lại.

3

Bạn có thể chèn tất cả các chuỗi của mình vào một số trie (còn gọi là cây tiền tố). Sau đó đi qua các trie từ gốc cho đến khi bạn tìm thấy một nút với nhiều hơn một đứa trẻ (hoặc chỉ dừng lại chèn chuỗi khi bạn sẽ phải nối thêm một đứa con thứ hai vào một nút).

+0

Vì vậy, nếu chuỗi đầu tiên là "a", và chuỗi thứ hai là "b", tôi vẫn phải chèn 43 triệu chuỗi khác vào bộ ba? ;-p –

+0

Điểm tốt, tôi đã chỉnh sửa câu trả lời của mình. – omz

+0

Về mặt lý thuyết, tôi muốn nói, "chuyển sang chuỗi tiếp theo" thay vì "ngừng chèn chuỗi" khi bạn đến điểm chi nhánh. Sau này có thể đề nghị dừng hoàn toàn, trái ngược với "khi chèn chuỗi, ngừng chèn (chuỗi đó) khi ...". Nhưng tôi biết ý anh là gì. –

6

Edit: cho câu hỏi làm rõ:

  1. Sắp xếp các dây
  2. Tìm tiền tố chung dài nhất của mỗi cặp liền kề
  3. Sắp xếp và dedupe các tiền tố thông thường, sau đó loại bỏ bất kỳ đó là một tiền tố khắt khe của khác.

Thực tế, bước (3) chỉ yêu cầu bạn xóa bất kỳ khoản tiền nào là tiền tố/tiền tố của tài khoản khác, mà bạn có thể thực hiện bằng trie hoặc bất kỳ thứ gì thay vì sắp xếp. Trong thực tế, có thể toàn bộ điều có thể được thực hiện nhanh hơn với một trie được chú thích phù hợp - nếu bạn bao gồm "đếm" tại mỗi nút thì bạn đang tìm kiếm chính xác các nút có số lượng 2+, không có con đếm 2+.

Nhưng sắp xếp được tích hợp và khi bạn đã sắp xếp, bạn có thể phát hiện tiền tố bằng cách xem các mục lân cận, vì vậy có thể ít nỗ lực hơn.

[Câu trả lời gốc:

Chỉ một thao tác một lần, tìm tiền tố chung dài nhất giữa tất cả các chuỗi?

Tôi có thể làm điều đó theo độ dài của tiền tố. Trong pseudo-code, và giả sử chuỗi nul-chấm dứt:

prefixlen = strlen(first_string); 
foreach string in the list { 
    for (i = 0; i < prefixlen; ++i) { 
     if (string[i] != first_string[i]) { 
      prefixlen = i; 
      break; 
     } 
    } 
    if (prefixlen == 0) break; 
} 

common_prefix = substring(firststring, 0, prefixlen); 

]

+1

+1, nếu đó là một hoạt động một lần, sử dụng một trie incurs trong một hình phạt thời gian/không gian. – abeln

+0

Ngoài ra, nếu chuỗi đầu vào xảy ra theo thứ tự sắp xếp, bạn chỉ cần so sánh chuỗi đầu tiên và cuối cùng. –

+0

Đây không phải là chính xác những gì tôi cần. Tôi không cần tiền tố chung dài nhất của n chuỗi. Thay vào đó tôi cần m tiền tố phổ biến dài nhất cho n chuỗi. – cfischer

0
  1. Chèn tất cả các chuỗi thành một cấu trúc dữ liệu Trie.
  2. DFS từ gốc để tìm nút đầu tiên có nhiều hơn 1 cạnh đi ra khỏi nó.
  3. đường dẫn từ gốc đến nút được tính toán trong bước 2 cung cấp tiền tố chung dài nhất cho tất cả tập hợp các chuỗi.
Các vấn đề liên quan