2009-10-05 41 views
19

Đối với dự án Cấu trúc dữ liệu, tôi phải tìm đường đi ngắn nhất giữa hai từ (như "cat""dog"), chỉ thay đổi một chữ cái tại một thời điểm. Chúng tôi được đưa ra một danh sách từ Scrabble để sử dụng trong việc tìm kiếm con đường của chúng tôi. Ví dụ:Đường dẫn ngắn nhất để chuyển một từ thành

cat -> bat -> bet -> bot -> bog -> dog 

Tôi đã giải quyết vấn đề bằng cách sử dụng tìm kiếm đầu tiên, nhưng tôi đang tìm kiếm thứ gì đó tốt hơn (tôi đã đại diện cho từ điển với một bộ ba).

Vui lòng cho tôi một số ý tưởng về phương pháp hiệu quả hơn (về mặt tốc độ và bộ nhớ). Một cái gì đó vô lý và/hoặc thách thức được ưa thích.

Tôi đã hỏi một trong những người bạn của tôi (anh ấy là đàn em) và anh ấy nói rằng có số giải pháp hiệu quả cho vấn đề này. Anh ấy nói tôi sẽ học tại sao khi tôi học khóa học thuật toán. Bất kỳ ý kiến ​​về điều đó?

Chúng ta phải chuyển từ từng chữ. Chúng tôi không thể đi cat -> dat -> dag -> dog. Chúng tôi cũng phải in ra các traversal.

+6

Trong ví dụ của bạn, tại sao đặt cược vào đó? Bạn đã thay đổi cùng một chữ cái hai lần liên tiếp, nó phải đọc: mèo -> bat -> bot -> bog -> dog – CaffGeek

+0

trùng lặp http://stackoverflow.com/questions/11811918/how-to-compute-shortest- khoảng cách giữa hai từ/hai từ/11813399 # 11813399 –

+0

Dacman, bạn có muốn chia sẻ hiệu suất của bạn được cải thiện bằng cách sử dụng chẩn đoán so với BFS không? –

Trả lời

14

MỚI ĐÁP

Với bản cập nhật gần đây, bạn có thể thử A * với khoảng cách Hamming là một heuristic. Đây là một heuristic, có thể chấp nhận vì nó sẽ không đánh giá quá cao xa

OLD ĐÁP

Bạn có thể thay đổi năng động chương trình sử dụng để tính toán Levenshtein distance để có được những chuỗi các hoạt động.

CHỈNH SỬA: Nếu có số lượng chuỗi không đổi, thì sự cố có thể giải được trong thời gian đa thức. Khác, đó là NP-cứng (đó là tất cả có trong wikipedia) .. giả sử bạn của bạn đang nói về vấn đề là NP-cứng.

CHỈNH SỬA: Nếu các chuỗi của bạn có chiều dài bằng nhau, bạn có thể sử dụng Hamming distance.

+3

Đưa ra ví dụ cho khoảng cách Hamming. – Zed

+2

Bạn không thể sửa đổi hàm Levenshtein để làm điều này, bởi vì bạn có một từ điển hạn chế các từ hợp lệ - và vì vậy đường dẫn hợp lệ ngắn nhất có thể dài hơn rất nhiều so với số ký tự trong chuỗi. –

+0

^Suy nghĩ của tôi chính xác. – dacman

0

Bạn có thể tìm thấy chuỗi phổ biến dài nhất, và do đó việc tìm các chữ cái phải được thay đổi.

1

Đây là sự cố dynamic programming điển hình. Kiểm tra vấn đề Chỉnh sửa khoảng cách.

+3

Không. Đọc kỹ câu hỏi. Có một từ điển cố định, vì vậy khoảng cách chỉnh sửa có rất ít sự liên quan. – ShreevatsaR

+1

Tại sao điều này lại được bình chọn? Nó không trả lời những gì được hỏi. –

0

Cảm giác ruột của tôi là bạn của bạn là chính xác, trong đó không phải là một giải pháp hiệu quả hơn, nhưng đó là giả định bạn đang tải lại từ điển mỗi lần. Nếu bạn muốn giữ một cơ sở dữ liệu chuyển tiếp chung, thì chắc chắn sẽ có một phương pháp hiệu quả hơn để tìm giải pháp, nhưng bạn cần phải tạo các chuyển tiếp trước đó và phát hiện chuyển tiếp nào hữu ích (vì bạn không thể tạo tất cả!) có lẽ là một nghệ thuật của riêng nó.

3

Có các phương pháp hiệu quả khác nhau cho các liên kết tìm kiếm - bạn có thể tạo biểu đồ hoàn chỉnh cho mỗi độ dài từ hoặc bạn có thể tạo ví dụ BK-Tree, nhưng bạn của bạn là đúng - BFS là thuật toán hiệu quả nhất. Tuy nhiên, có một cách để cải thiện đáng kể thời gian chạy của bạn: Thay vì thực hiện một BFS đơn từ nút nguồn, thực hiện hai tìm kiếm đầu tiên, bắt đầu ở cuối biểu đồ và chấm dứt khi bạn tìm thấy một nút chung trong bộ biên giới của họ. Số lượng công việc bạn phải làm là khoảng một nửa những gì được yêu cầu nếu bạn tìm kiếm từ chỉ một đầu.

+0

Lưu ý rằng phương pháp này chỉ hoạt động cho các đồ thị không có trọng số, tôi tin. Trên các đồ thị có trọng số (trong đó một số cạnh là "chi phí nhiều hơn" hoặc dài hơn các loại khác), sử dụng tìm kiếm hai hướng theo cách tương tự không đảm bảo đường đi ngắn nhất được tìm thấy. Xem [liên kết này] (http://www.cs.princeton.edu/courses/archive/spr06/cos423/Handouts/EPP%20shortest%20path%20algorithms.pdf) và [chủ đề này] (http: // stackoverflow .com/questions/4253413/chấm dứt-tiêu chí-cho-hai chiều-tìm kiếm). Nhưng trong trường hợp này, các bước giữa các từ khác nhau một chữ cái đều giống nhau –

9

Với từ điển, BFS là tối ưu, nhưng thời gian chạy cần thiết tỷ lệ thuận với kích thước của nó (V + E). Với chữ cái n, từ điển có thể có ~ a^n entires, trong đó có kích thước bảng chữ cái. Nếu từ điển chứa tất cả các từ nhưng từ đó phải ở cuối chuỗi, thì bạn sẽ đi qua tất cả các từ có thể nhưng sẽ không tìm thấy bất kỳ từ nào. Đây là biểu đồ truyền tải, nhưng kích thước có thể lớn theo cấp số nhân.

Bạn có thể tự hỏi liệu có thể thực hiện nhanh hơn không - để duyệt cấu trúc "thông minh" và thực hiện nó trong thời gian đa thức. Câu trả lời là, tôi nghĩ là không.

Vấn đề:

Bạn đang đưa ra một (tuyến tính) cách nhanh chóng để kiểm tra xem một từ trong từ điển, hai chữ u, v và để kiểm tra nếu có một chuỗi u -> một -> a -> ... -> a n -> v.

là NP-hard.

Proof: Lấy một số ví dụ 3SAT, như

(p hoặc q hay không r) và (p hay không q hoặc r)

Bạn sẽ bắt đầu với 0 000 00 và là để kiểm tra xem có thể đi đến 2 222 22.

Ký tự đầu tiên sẽ là "chúng ta đã hoàn thành", ba bit tiếp theo sẽ điều khiển p, q, r và hai tiếp theo sẽ điều khiển mệnh đề.

từ phép là:

  • Bất cứ điều gì mà bắt đầu với 0 và chỉ chứa 0 và 1 của
  • Bất cứ điều gì mà bắt đầu với 2 và là hợp pháp. Điều này có nghĩa là nó bao gồm 0 và 1 (ngoại trừ ký tự đầu tiên là 2, tất cả các mệnh đề bit được thiết lập đúng theo bit biến, và chúng được đặt thành 1 (do đó, điều này cho thấy công thức là thỏa mãn)
  • Bất cứ điều gì bắt đầu với ít nhất hai của 2 và sau đó bao gồm 0 và 1 (biểu thức chính quy: 222 * (0 + 1) *, như 22221101 nhưng không 2212001

Để sản xuất 2 222 22 từ 0 000 00, bạn phải thực hiện theo cách này:

(1) Lật các bit thích hợp - ví dụ 0 100 111 trong bốn bước. Điều này đòi hỏi phải tìm giải pháp 3SAT

(2) Thay đổi bit đầu tiên thành 2: 2 100 111. Ở đây bạn sẽ được xác minh đây thực sự là giải pháp 3SAT.

(3) Thay đổi 2 100 111 -> 2 200 111 -> 2 220 111 -> 2 222 111 -> 2 222 211 -> 2 222 221 -> 2 222 222.

Những quy định thi hành mà bạn không thể lừa (kiểm tra). Đi đến 2 222 22 chỉ có thể nếu công thức là thỏa đáng, và kiểm tra đó là NP-cứng. Tôi cảm thấy nó thậm chí có thể khó hơn (#P hoặc FNP có lẽ) nhưng NP-độ cứng là đủ cho mục đích đó tôi nghĩ.

Chỉnh sửa: Bạn có thể quan tâm đến disjoint set data structure. Điều này sẽ lấy từ điển và từ nhóm của bạn có thể được liên lạc với nhau. Bạn cũng có thể lưu trữ một đường dẫn từ mọi đỉnh đến gốc hoặc một số đỉnh khác. Điều này sẽ cho bạn một con đường, không nhất thiết là con đường ngắn nhất.

+0

Tóm tắt tuyệt vời. Nếu tác giả ban đầu đang tìm kiếm điều gì đó thực sự sáng tạo, khoảng cách chỉnh sửa có thể được sử dụng kết hợp với biểu đồ từ tiếp cận dưới dạng hàm thể dục cho thuật toán di truyền. Đầu ra là đường dẫn thông qua biểu đồ từ một từ bắt đầu đến từ kết thúc, vì vậy câu trả lời hay nhất sẽ là ngắn nhất. (Trong khi mát mẻ, điều này sẽ tìm thấy câu trả lời nhanh nhất, nhưng sẽ không mang lại một câu trả lời dứt khoát. Rất TS.) Tôi muốn gắn bó với thế giới thực. Loại bỏ các chu kỳ, liệt kê các đường dẫn và tìm ra 'tốt nhất' bằng cách sử dụng các gợi ý ở trên. Điều này được gắn thẻ 'Java' vì vậy hãy thử JGraphT. –

+0

Mát mẻ, không phải thường xuyên nhìn thấy bằng chứng NP-độ cứng trong câu trả lời Stackoverflow. :-) Tôi quá nghi ngờ vấn đề này là khó hơn NP (PSPACE-hoàn thành?) Nếu từ điển được đưa ra chỉ đơn giản là một thành viên oracle ... nhưng nếu từ điển thực sự được đưa ra trong đầu vào, sau đó vấn đề có thể trivially được thực hiện trong đa thức thời gian, như kích thước từ điển là một phần của đầu vào (đó là lỗ hổng trong bằng chứng NP-độ cứng của bạn). – ShreevatsaR

1

Điều bạn đang tìm kiếm được gọi là Khoảng cách chỉnh sửa. Có nhiều loại khác nhau.

Từ (http://en.wikipedia.org/wiki/Edit_distance): "Trong lý thuyết thông tin và khoa học máy tính, khoảng cách chỉnh sửa giữa hai chuỗi ký tự là số hoạt động cần thiết để chuyển đổi một trong số chúng thành một chuỗi khác".

Bài viết này về Jazzy (API java kiểm tra chính tả) có một cái nhìn tổng quan tốt đẹp của những loại so sánh (đó là một vấn đề tương tự - cung cấp điều chỉnh đề xuất) http://www.ibm.com/developerworks/java/library/j-jazzy/

2

Bạn có thể làm cho nó một chút nhanh hơn bằng cách loại bỏ các từ không phải là độ dài phù hợp, trước tiên. Thêm từ điển hạn chế sẽ phù hợp với bộ nhớ cache của CPU. Có lẽ là tất cả.

Ngoài ra, tất cả các so sánh strncmp (giả sử bạn tạo mọi chữ thường) có thể là so sánh memcmp, hoặc thậm chí so sánh không được kiểm soát, có thể là một tăng tốc.

Bạn có thể sử dụng một số ma thuật tiền xử lý và biên dịch khó khăn nhiệm vụ cho độ dài từ đó hoặc cuộn một vài biến thể tối ưu hóa của tác vụ cho độ dài từ chung. Tất cả những so sánh thêm có thể 'biến mất' cho niềm vui chưa được kiểm soát thuần túy.

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