CHƯƠNG 1. TỔNG QUAN VỀ SO KHỚP
1.1.2 Các thuật toán so khớp chính xác cổ điển
Cửa sổ trượt Chuỗi văn bản T
Mẫu P
Cửa sổ trượt Chuỗi vănbản T
Mẫu P
Các kỹ thuật so khớp chính xác cổ điển được xây dựng dựa trên số ký tự được so sánh. Sự khác biệt của các thuật toán là quá trình tính toán xác định số ký tự được dịch chuyển sau mỗi lần so sánh. Việc so sánh có thể được tiến hành từ trái qua phải hay từ phải qua trái, vị trí ký tự so sánh có thể là dựa trên tiền tố, hậu tố,... Các thuật toán so khớp điển hình có thể kể đến gồm:
Thuật toán Brute Force [7]: đây là thuật toán đầu tiên và đơn giản nhất được biết đến. Thuật toán Brute Force kiểm tra tất cả các vị trí trong văn bản giữa 0 và n - m, có xuất hiện của mẫu P hay không. Sau đó, sau mỗi lần so sánh sẽ dịch chuyển mẫu đúng một vị trí sang bên phải. Thuật toán Brute Force không yêu cầu giai đoạn tiền xử lý và một không gian thêm liên tục thêm vào mẫu và các văn bản. Trong giai đoạn tìm kiếm so sánh ký tự văn bản có thể được thực hiện theo thứ tự. Độ phức tạp của giai đoạn tìm kiếm này làO m( n).
Thuật toán KMP (1972) [8] được đề xuất bởi Knuth, Morris và Pratt dựa trên tiếp cận tiền tố bằng cách không so sánh mẫu với lần lượt từng vị trí trong văn bản như trong thuật toán Brute Force mà có thể dịch chuyển mẫu sang phải văn bản một số vị trí do sử dụng những thông tin của lần thử trước cho lần thử sau. Ý tưởng chính của phương pháp này như sau : trong quá trình tìm kiếm vị trí của mẫu P trong xâu gốc T, nếu tìm thấy một vị trí sai ta chuyển sang vị trí tìm kiếm tiếp theo và quá trình tìm kiếm sau này sẽ được tận dụng thông tin từ quá trình tìm kiếm trước để không phải xét các trường hợp không cần thiết. Thuật toán KMP cải tiến thời gian thực hiện bằng cách giảm số phép so sánh dựa trên các mẫu được tiền xử lý để tìm ra các mẫu con từ đó xây dựng mảng Next để xác định ký tự tiếp theo trong mẫu được kiểm tra dựa trên mô hình Automat. Việc so khớp được thực hiện dựa trên các ký tự trong xâu văn bản T và dịch trạng thái của mảng Next. Ưu điểm của thuật toán KMP là con trỏ trên văn bản T không bao giờ bị giảm lùi lại. Thuật toán KMP dùng ít phép so sánh hơn thuật toán Brute Force, độ phức tạp thời gian và không gian để xây dựng bảng kmpNext là O(m)và độ phức tạp tính toán của thuật toán là O(m+n) = O(n).
Thuật toán Boyer-Moore (1977) [12] được xây dựng để kiểm tra các ký tự của mẫu từ phải sang trái. Khi phát hiện sự khác nhau sẽ tiến hành dịch mẫu sang phải văn bản một số vị trí với hai cách dịch chuyển mẫu là Good-suffix và Bad-character.
Khoảng cách dịch chuyển Good-suffix gần giống trong thuật toán KMP, chúng ta dịch
mẫu sang phải văn bản sao cho tại vị trí mới có đoạn u trên mẫu P khớp với đoạn u trên văn bản T và ký tự c trên mẫu P ngay trước u phải khác a. Ta chọn đoạn dịch ngắn nhất. Nếu không có cả đoạn u trong P, ta chọn sao cho phần đuôi dài nhất của u xuất hiện ở đầu mẫu P. Với Bad-character, khi xuất hiện sự khác nhau giữa mẫu P và văn bản T với bT i j P i a, ta sẽ dịch sao cho có một ký tự giống b trên mẫu khớp vào vị trí đó, nếu có nhiều vị trí xuất hiện b trên mẫu ta chọn vị trí bên phải nhất.
Nếu không có ký tự b nào trong mẫu ta sẽ dịch sao cho ký tự trái nhất của mẫu vào vị trí ngay sau ký tự T i jb để đảm bảo sự ăn khớp. Hai hướng tiếp cận sẽ tạo ra 2 giá trị dịch chuyển khác nhau, từ đó sẽ lựa chọn giá trị lớn hơn làm giá trị dịch chuyển.
Độ phức tạp trung bình của thuật toán BM là O(n/m) trong trường hợp các ký tự trong T không thường xuyên xuất hiện trong mẫu P, trong trường hợp xấu nhất là O(n+m).
Thời gian thực thi của BM sẽ giảm khi độ dài của mẫu tăng.
Thuật toán Boyer-Moore-Horspool (1980) [7] dựa trên việc tìm kiếm ký tự lỗi với hai thủ tục tìm kiếm đơn giản dùng để tìm ký tự đầu tiên (SFC-search for first character) và quét ký tự có tần suất xuất hiện ít nhất (SLFC- scan for lowest frequency character) nhằm hỗ trợ thuật toán Boyer-Moore để quá trình tìm kiếm được thực hiện không phụ thuộc vào trạng thái của chuỗi. Đầu tiên, giai đoạn tiền xử lý sẽ sinh ra mảng NEXT để quyết định việc di chuyển các vị trí tìm kiếm tiếp theo. Mảng NEXT có vai trò rất quan trọng trong việc thực thi thuật toán, vị trí của ký tự tiếp theo trong chuỗi mẫu được định nghĩa như một con trỏ tham chiếu. Quá trình xây dựng mảng NEXT dựa trên tập qui tắc sau: (i) với mỗi ký tự trong chuỗi mẫu, xác định sự khác nhau về độ dài mẫu dựa vào vị trí của con trỏ NEXT [c] của chuỗi mẫu. (ii) với mỗi ký tự không thuộc chuỗi mẫu, xác định tăng chiều dài của chuỗi mẫu tại NEXT [c]. Nội dung của con trỏ tham chiếu được sử dụng như tiền điều kiện để sinh ra mảng NEXT cho phép thực thi dịch chuyển sang vị trí tiếp theo trong quá trình tìm kiếm. Quá trình so khớp có thể được thực hiện từ trái sang phải hay từ phải sang trái. Cách tìm kiếm hiệu quả được thực hiện từ phải qua trái cho phép nếu phát hiện không khớp thì không cần xuất phát từ vị trí bắt đầu của chuỗi con mà vị trí hiện thời có thể bắt đầu từ vị trí các chuỗi con tiếp theo. Điều này cho phép hạn chế số lượng các phép so sánh cần thực hiện và được gọi là thuật toán so khớp chuỗi AN (Array Next).
Thuật toán Apostolico-Giancarlo (1986) [7] dựa trên tiếp cận ghi nhớ tất cả hậu tố của các mẫu được tìm thấy trong văn bản sử dụng bảng dịch chuyển kmpNext để tính số lần dịch chuyển. Từ đó tính toán khoảng cách dịch chuyển phù hợp đến vị trí ký tự cuối cùng trong mẫu với mỗi lần thử. Giai đoạn tiền xử lý bao gồm công đoạn tính toán bảng kmpNext[] và số nguyên . Nó có thể bị mất O(m) không gian và thời gian xử lý. Việc tìm kiếm mất O(n) thời gian, do vậy thuật toán thuật toán Apostolico–
Giancarlo thực hiện so sánh 3
2n ký tự văn bản trong trường hợp xấu nhất.
Thuật toán Quick Search (1990) [7] là cải tiến đơn giản hóa của thuật toán Boyer Moore chỉ sử dụng bảng dịch “Bad-character shift” khi xác định số bước dịch chuyển trong trường hợp xấu nhất. Thuật toán Quick Search thực hiện rất nhanh với tập các mẫu ngắn và các văn bản lớn. Sau mỗi lần thử, cửa sổ trượt sẽ dịch chuyển sang vị trí tiếp theo trong gói tin dựa vào bảng qsBC, độ dài mỗi lần dịch ít nhất sẽ bằng 1.
Thuật toán Boyer-Moore-Smith (1991) [62] là sự kết hợp việc đánh giá hiệu quả từ lựa chọn số ký tự dịch chuyển lớn nhất dựa trên tính toán các bước dịch chuyển trong văn bản bên phải nhất của ký tự đang xét.
Thuật toán Colussi Algorithm (1991) [62]cũng là một cải tiến từ thuật toán KMP bằng cách chia các vị trí ký tự trong mẫu thành hai tập con tách biệt. Các vị trí trong tập thứ nhất sẽ được duyệt từ trái quá phải và các vị trí không khớp sẽ được duyệt lại trong tập con thứ hai từ phải qua trái.
Thuật toán Raita (1992) [62]: dựa trên sự hiệu chỉnh từ thuật toán Boyer- Moore-Horspool với chiến lược tìm kiếm bắt đầu bằng cách so sánh ký tự bên phải nhất của cửa sổ trượt và đếm từng vị trí tương ứng. Với các vị trí khớp sẽ tiếp tục so sánh ký tự bên trái của cửa sổ dịch chuyển với ký tự bên trái của mẫu. Cuối cùng sẽ so sánh toàn bộ các ký tự từ phải qua trái đến khi mẫu được tìm thấy hoặc loại bỏ mẫu đó.
Thuật toán Turbo-BM (1994) [62]: tiếp tục là một cải tiến của thuật toán Boyer-Moore bằng cách ghi nhớ các xâu con của văn bản T đã được xuất hiện trong phần hậu tố của mẫu khi so sánh các ký tự cuối cùng.
Thuật toán Berry-Ravindran (1999) [62] là cải tiến của thuật toán Quick Search dựa trên việc sử dụng các luật cho phép thực hiện nhanh các lần lặp với các ký tự không khớp được tìm thấy.
Ngồi ra cịn rất nhiều thuật tốn khác như: Not So Nạve, Simon, Galil- Giancarlo, Horspool, Zhu-Takaoka, Smith, Two way, KMPSkip, Alpha Skip,…