Giới thiệu về so khớp chuỗi chính xác

Bài toán

So khớp chuỗi chính xác (exact string matching) là một trong những bài toán nền tảng của khoa học máy tính. Cho trước một mẫu (pattern) x có độ dài m và một văn bản (text) y có độ dài n, cả hai được viết trên cùng một bảng chữ cái (alphabet) Σ có kích thước σ. Nhiệm vụ là tìm tất cả các vị trí mà mẫu x xuất hiện trong văn bản y.

Nói chính xác hơn, ta cần tìm mọi chỉ số j (với 0 ≤ j ≤ n - m) sao cho:

y[j .. j + m - 1] = x[0 .. m - 1]

nghĩa là y[j + i] = x[i] với mọi i từ 0 đến m - 1. Khi điều kiện này thỏa mãn, ta nói mẫu xuất hiện tại vị trí j.

Bài toán này xuất hiện ở khắp nơi: tìm kiếm trong trình soạn thảo văn bản, lọc gói tin trong mạng, tra cứu ADN trong tin sinh học, công cụ tìm kiếm, chống virus dựa trên chữ ký, v.v. Vì dữ liệu có thể rất lớn, hiệu năng của thuật toán so khớp chuỗi có ý nghĩa thực tiễn quan trọng.

Quy ước ký hiệu

Trong toàn bộ tài liệu này, ta thống nhất các ký hiệu sau:

Thông thường ta giả định m ≤ n, vì nếu mẫu dài hơn văn bản thì hiển nhiên không có xuất hiện nào.

Cửa sổ trượt, phép thử và bước dịch

Hầu hết các thuật toán so khớp chuỗi hoạt động theo mô hình cửa sổ trượt (sliding window). Ta hình dung một cửa sổ có độ dài m đúng bằng độ dài mẫu, đặt chồng lên văn bản. Ban đầu cửa sổ nằm ở đầu văn bản, canh thẳng với y[0 .. m-1].

Tại mỗi vị trí của cửa sổ, thuật toán thực hiện một phép thử (attempt): so sánh các ký tự của mẫu với các ký tự văn bản nằm trong cửa sổ, theo một thứ tự nào đó. Phép thử có thể kết thúc thành công (tìm thấy một xuất hiện) hoặc thất bại (gặp một cặp ký tự không khớp, gọi là điểm sai lệch — mismatch).

Sau mỗi phép thử, thuật toán dịch cửa sổ sang phải một khoảng gọi là bước dịch (shift). Điểm mấu chốt phân biệt các thuật toán chính là: chúng dịch cửa sổ bao xa và dựa trên thông tin gì. Thuật toán ngây thơ nhất luôn dịch đúng một vị trí; các thuật toán tinh vi hơn tận dụng thông tin thu được trong phép thử để dịch xa hơn mà vẫn không bỏ sót xuất hiện nào.

Phân loại theo thứ tự so sánh ký tự

Một cách phân loại hữu ích là dựa trên thứ tự mà thuật toán so sánh các ký tự bên trong cửa sổ:

Các đại lượng độ phức tạp quan tâm

Bảng tóm tắt các nhóm thuật toán tiêu biểu

Thuật toánTiền xử lýTìm kiếmBộ nhớ phụHướng so sánh
Brute ForcekhôngO(mn)O(1)trái → phải
Morris-PrattO(m)O(n+m)O(m)trái → phải
Knuth-Morris-PrattO(m)O(n+m)O(m)trái → phải
Otomat hữu hạn đơn địnhO(mσ)O(n)O(mσ)trái → phải
Shift-OrO(m+σ)O(n)O(σ)trái → phải
Karp-RabinO(m)O(mn) xấu nhất, O(n+m) kỳ vọngO(1)trái → phải
Boyer-MooreO(m+σ)O(mn) xấu nhất, dưới tuyến tính TBO(m+σ)phải → trái
HorspoolO(m+σ)O(mn) xấu nhất, dưới tuyến tính TBO(σ)phải → trái

Các mục tiếp theo trình bày chi tiết từng thuật toán: ý tưởng, cơ chế tiền xử lý, cài đặt bằng C, và ví dụ minh họa.

Tài liệu tham khảo