Điểm bắt đầu tìm kiếm chuỗi gần đúng là khoảng cách Levenshtein . Thuật toán này đếm số lần chỉnh sửa ký tự đơn (chèn, xóa và thay thế) để thay đổi một từ thành một từ khác.
Một ví dụ về điều này là kitten
-> sitting
có khoảng cách chỉnh sửa là ba
- k itten -> s itten (thay thế 's' cho 'k')
- sitt e n -> sitt i n (thay thế 'i' cho 'e')
- sittin -> sittin g (thêm 'g' ở cuối)
Có các biến thể của thuật toán này, đáng chú ý là khoảng cách Damensau của Levenshtein cho phép hoán vị hai ký tự liền kề ('hte' thành 'the' có khoảng cách DL là 1 và khoảng cách Levenshtein là 2) và do đó thường thích hợp hơn cho kiểm tra chính tả. Các biến thể khác tồn tại cho các ứng dụng trong đó khoảng trống là quan trọng (chuỗi DNA).
Khoảng cách Levenshtein rất nổi tiếng và không quá khó để tìm thấy (tôi đã từng tìm cách thực hiện nó như một chức năng trong orory - nó nhanh hơn nhiều so với việc kéo xuống tất cả dữ liệu và sau đó chạy bên mã truy vấn). Rosettacode có vô số (54) ý nghĩa về khoảng cách Levenshtein (lưu ý rằng một số ngôn ngữ có phần này như một phần của thư viện chuỗi ở đâu đó - nếu bạn đang làm Java, hãy nhìn vào apache commons lang ). Wikibooks có 31 triển khai và một cái nhìn lướt qua hai cái không hiển thị cùng một mã cho cùng một ngôn ngữ.
Cách thức hoạt động này là nó xây dựng một ma trận tương ứng với mối quan hệ giữa hai chuỗi:
.kitten
.0123456
s1123456
i2212345
t3321234
t4432123
i5543223
n6654332
g7765443
Các .
hàng và cột đại diện cho rằng bạn có thể nhận được vào chuỗi mục tiêu của 'chỉ' chèn mỗi lá thư từ một chuỗi rỗng. Đây không phải là trường hợp lý tưởng, nhưng nó ở đó để gieo mầm thuật toán.
Nếu giá trị giống với điểm đó ('i' == 'i'), giá trị này giống với giá trị theo đường chéo ở bên trái. Nếu hai điểm không giống nhau ('s'! = 'K'), giá trị là mức tối thiểu của:
- đường chéo lên và sang trái + 1 (thay thế)
- trực tiếp trên + 1 (một chèn)
- trực tiếp bên trái + 1 (xóa)
Giá trị trả về khoảng cách chỉnh sửa là giá trị ở phía dưới bên phải của ma trận.
Nếu bạn theo dõi từ phía dưới bên phải sang phía trên bên trái với mức tối thiểu, bạn có thể thấy các chỉnh sửa được thực hiện:
.kitten
.0. .
s.1 .
i 1 .
t 1 .
t 1.
i.....2
n 2
g......3
Hãy lưu ý rằng đây là cách tiếp cận khá bộ nhớ. Nó có thể được giảm phạm vi bộ nhớ bằng cách không xây dựng ma trận đầy đủ - tất cả các thuật toán quan tâm là một tập hợp con của dữ liệu và nó có thể được giảm từ N*M
không gian sang 2*max(N,M)
không gian bằng cách chỉ lưu trữ hàng trước đó (và những gì đã được tính toán trên hiện tại hàng). Code Project cho thấy làm thế nào điều này có thể được thực hiện (với mã C # để tải xuống).