Tìm hiểu thuật toán so khớp xâu kí tự

8 1.4K 19
Tìm hiểu thuật toán so khớp xâu kí tự

Đang tải... (xem toàn văn)

Thông tin tài liệu

1. Mở đầuTrong ngành Khoa học máy tính, các thuật toán so khớp xâu kí tự (hay còn gọi là thuậttoán tìm kiếm chuỗi) là một trong những bài toán cơ bản và quan trọng nhất. Mục đíchcủa thuật toán là tìm kiếm vị trí của các chuỗi con (còn được gọi là các pattern) trongmột chuỗi kí tự hoặc một văn bản lớn. Bài toán này có tính ứng dụng quan trọng trênthực tế. Chẳng hạn như bài toán Tìm các pattern trong các chuỗiDNA là bài toán cơbản đối với ngành Tin sinh học. Các phần mềm diệt virus hiện đại có chứa hàng chụctriệu các pattern là các “dấu hiệu” (virus signature) của các con virus mà máy tính đãbiết. Khi quét virus thì phần mềm diệt virus phải tìm kiếm các pattern này trong cácfiles hay bộ nhớ của máy…12. Thuật toán KnuthMorris Pratt2.1. Sơ lượcNếu chỉ tính các thuật toán tìm kiếm sự xuất hiện của một chuỗi đơn cho trước bêntrong một chuỗi khác thì đã có đến hàng trăm thuật toán khác nhau, đã được thống kêở tài liệu tham khảo 2. Thuật toán KnuthMorris Pratt (KMP) là một trong số hàngtrăm thuật toán đó.Thuật toán KMP được tìm ra bởi hai nhà Khoa học máy tính, Giáo sư danh dự của Đạihọc Stanford là Donald Ervin Knuth và Vaughan Ronald Pratt cùng với Giáo sưngười Mĩ James Hiram Morris vào năm 1974, họ nghiên cứu độc lập với nhau, tuynhiên, sau đó cả ba người đã cùng công bố thuật toán này vào năm 1977. 3Ý tưởng của thuật toán KMP đơn giản là tìm kiếm sự xuất hiện của một “từ” W trongmột “xâu văn bản” S bằng cách tiếp tục quá trình tìm kiếm khi không phù hợp, chínhtừ cho ta đầy đủ thông tin để xác định vị trí bắt đầu của kí tự so sánh tiếp theo, do đóbỏ qua quá trình kiểm tra lại các kí tự đã so sánh trước đó.

Tìm hiểu thuật toán so khớp xâu kí tự (string matching) Nguyễn Thành Đạt, Ngô Văn Dũng – K59B – Khoa Công nghệ Thông tin – Đại học Sư phạm Hà Nội Hướng dẫn: TS Phạm Đức Đông – Khoa Toán tin – Đại học Sư phạm Hà Nội Tóm tắt: Đề tài tập lớn môn học trình bày tìm hiểu cách thức hoạt động hai số nhiều thuật toán so khớp xâu kí tự (string searching algorithm/ string matching algorithm) thuật toán Knuth-Morris-Pratt (KMP) thuật toán Rabin-Karp Bên cạnh việc đánh giá độ phức tạp hai thuật toán, so sánh tính khả dụng chúng với thuật toán khác để giải toán tương tự với trường hợp cụ thể, cài đặt chương trình mô thuật toán ngôn ngữ lập trình C++ Mở đầu Trong ngành Khoa học máy tính, thuật toán so khớp xâu kí tự (hay gọi thuật toán tìm kiếm chuỗi) toán quan trọng Mục đích thuật toán tìm kiếm vị trí chuỗi (còn gọi pattern) chuỗi kí tự văn lớn Bài toán có tính ứng dụng quan trọng thực tế Chẳng hạn toán Tìm pattern chuỗi-DNA toán ngành Tin sinh học Các phần mềm diệt virus đại có chứa hàng chục triệu pattern “dấu hiệu” (virus signature) virus mà máy tính biết Khi quét virus phần mềm diệt virus phải tìm kiếm pattern files hay nhớ máy…[1] Thuật toán Knuth-Morris-Pratt 2.1 Sơ lược Nếu tính thuật toán tìm kiếm xuất chuỗi đơn cho trước bên chuỗi khác có đến hàng trăm thuật toán khác nhau, thống kê tài liệu tham khảo [2] Thuật toán Knuth-Morris-Pratt (KMP) số hàng trăm thuật toán Thuật toán KMP tìm hai nhà Khoa học máy tính, Giáo sư danh dự Đại học Stanford Donald Ervin Knuth Vaughan Ronald Pratt với Giáo sư người Mĩ James Hiram Morris vào năm 1974, họ nghiên cứu độc lập với nhau, nhiên, sau ba người công bố thuật toán vào năm 1977 [3] Ý tưởng thuật toán KMP đơn giản tìm kiếm xuất “từ” W “xâu văn bản” S cách tiếp tục trình tìm kiếm không phù hợp, từ cho ta đầy đủ thông tin để xác định vị trí bắt đầu kí tự so sánh tiếp theo, bỏ qua trình kiểm tra lại kí tự so sánh trước 2.2 Hoạt động thuật toán Bài toán Input: Xâu văn S chuỗi W Output: Vị trí chuỗi W xâu văn S Ý tưởng Giả sử cho xâu văn S: CCABCABCABCABCD Tìm chuỗi W: ABCABCD xâu văn S Ta đưa thêm vào hai biến m i Trong đó: m vị trí tương ứng xâu S bắt đầu cho phép so sánh với W i số số w xác định kí tự so sánh m S CCABCABCABCABCD W ABCABCD i Bắt đầu so sánh kí tự tương ứng S W S[0] =”C” ≠ W[0] =”A” → m++ m S CCABCABCABCABCD W _ABCABCD i _0 S[1] =”C” ≠ W[0] =”A” → m++ m S CCABCABCABCABCD W ABCABCD i S[2] = W[0] =”A” → i++ S[3] = W[1] =”B” → i++ S[4] = W[2] =”C” → i++ S[5] = W[3] =”A” → i++ S[6] = W[4] =”B” → i++ m S CCABCABCABCABCD W ABCABCD i S[7] = W[5] =”C” → i++ m S CCABCABCABCABCD W i ABCABCD S[8] =”A” ≠ W[6] =”D” Nhận thấy kí tự “D” kí tự đầu xâu S , tăng m lên để bắt đầu xét từ đây, trả lại i=0 để xét lại từ kí tự đầu xâu W m _8 S CCABCABCABCABCD W _ABCABCD I _0 S[8] = S[0] = “A” → i++ S[9] = S[1] = “B” → i++ S[10] = S[2] = “C” → i++ S[11] = S[3] = “A” → i++ S[12] = S[4] = “B” → i++ S[13] = S[5] = “C” → i++ S[14] = S[6] = “D” → i++ Vậy tìm vị trí chuỗi W xâu văn S vị trí m=8 Thuật toán Input: Xâu văn (S) chuỗi (W) cần tìm Output: vị trí tìm thấy W xâu S BEGIN m = 0; i = 0; {MẢNG CHIỀU T}; // Sử dụng hàm xây dựng bảng KMP WHILE ((m+i) -1 ) THEN i = -1 ELSE i = 0; END; Writeln(“Không tìm chuỗi W xâu S”); END Trong thuật toán trên, bước cần xây dựng mảng chiều T Mảng T[i] sinh để khoảng cách từ kí tự thứ i tới kí tự giống kí tự (với điều kiện kí tự thứ i phải giống kí tự đó) Mảng chiều T gọi bảng KMP Xây dựng bảng KMP Input: chuỗi W cần tìm, mảng T Output: bảng KMP BEGIN Var pos, cnd: integer; pos = 2; cnd = 0; T[0] = -1; WHILE (pos < length(W)) DO BEGIN IF (W[pos-1] = W[cnd]) THEN BEGIN T[pos] = cnd + 1; pos = pos +1; cnd = cnd +1; END; ELSE IF (cnd > 0) THEN cnd = T[cnd] ELSE BEGIN T[pos] = 0; pos = pos +1; END; END; END Bảng KMP cho ví dụ sau: i W[i] A B C A B C T[i] -1 0 D T[0] = -1; Để tính T[1] cần tìm xâu “A” đồng thời xâu bắt đầu W → T[1] = 0; Tương tự, T[2] = 0; Tới W[3], ta thấy kí tự trùng với kí tự bắt đầu xâu W[0] Nhưng T[i] độ dài xâu dài trùng với xâu bắt đầu W tính đến W[i-1] nên T[3] = T[4] = 1; Tương tự, kí tự W[4] trùng với kí tự W[1] nên T[5] = 2, kí tự W[5] trùng với kí tự W[2] nên T[6] = 2.3 Đánh giá độ phức tạp thuật toán Thuật toán xây dựng bảng KMP có độ phức tạp O(n) với vòng lặp while Thuật toán chính có độ phức tạp O(k) với vòng lặp while Với trường hợp tốt nhất, chuỗi kí tự không bị lặp, độ phức tạp là O(n+k) Với trường hợp xấu nhất, độ phức tạp là O(n.k), chuỗi có các kí tự lặp lại nhiều lần Thuật toán Rabin-Karp 3.1 Sơ lược Thuật toán Rabin-Karp được phát minh bởi nhà khoa học máy tính người Israel Michael O.Rabin và nhà khoa học máy tính, nhà toán học lý thuyết người Mĩ Richard M.Karp vào năm 1987 [4] Thuật toán Rabin-Karp sử dụng hàm băm (hash) để tìm kiếm một chuỗi (pattern) một xâu văn bản Thuật toán sử dụng hàm băm để so sánh các giá trị băm của các chuỗi trước thực sự so sánh chuỗi Phương pháp này giúp tiết kiệm thời gian so sánh, đặc biệt là với các chuỗi so sánh dài 3.2 Hàm băm 3.2.1 Hàm băm bản Hàm băm giải thuật nhằm sinh giá trị băm tương ứng với khối liệu, chuỗi kí tự, đối tượng lập trình hướng đối tượng, Giá trị băm đóng vai gần khóa để phân biệt khối liệu, nhiên, người ta chấp tượng trùng khóa hay gọi đụng độ cố gắng cải thiện giải thuật để giảm thiểu đụng độ Hàm băm thường dùng bảng băm nhằm giảm chi phí tính toán tìm khối liệu tập hợp, nhờ việc so sánh giá trị băm nhanh việc so sánh khối liệu có kích thước lớn [5] Một hàm băm đơn giản tính toán giá trị băm dựa mã ASCII UNICODE ký tự Ví dụ với chuỗi nguồn “abcdefgh” và chuỗi cần tìm có độ dài thì giá trị băm đầu tiên sẽ là: h1 = a + b + c + d = 97 + 98 + 99 + 100 = 394 Giá trị băm tiếp theo cần tính là h2 = b + c + d + e = h1 – a + e = 394 – 97 + 101 = 398 Các hàm băm kiểu này có tốc độ tính toán cao, giá trị băm chỉ được tính toán lần đầu, các giá trị tiếp theo được tính từ giá trị trước đó Phép tính băm này không phụ thuộc vào số lượng kí tự cần tìm kiếm Tuy nhiên hàm băm này lại có khả gây trùng cao phép tính cộng giá trị quá đơn giản Chẳng hạn với chuỗi cần tìm “bcde” thì các chuỗi “cbed”, “ccdd”, “acak”…sẽ có cùng giá trị băm Vì vậy, một hàm băm tốt cần thỏa mãn các điều kiện sau: - Tính toán nhanh - Các khóa được phân bố đều bảng - Ít xảy đụng độ - Xử lý được các loại khóa có kiểu dữ liệu 3.2.2 Hàm băm Rolling hash khác Để giảm thiểu việc trùng giá trị băm mà đảm bảo tính toán giá trị băm nhanh dựa giá trị băm trước đó, hàm băm cho thuật toán Rabin-Karp sử dụng ý tưởng số Phép tính băm gọi Rolling hash Ý tưởng khai thác vùng nhớ lớn cách xem đoạn M-ký tự có văn khoá (key) bảng băm chuẩn Nhưng không cần thiết phải giữ bảng băm tổng thể, toán cài đặt cho khoá tìm kiếm; việc mà ta cần làm tính hàm băm cho M ký tự từ văn đơn giản kiểm tra xem chúng có với mẫu hay không Với hàm băm: h(k) = k mod q, q (kích thước bảng) số nguyên tố lớn Trong trường hợp này, chứa bảng băm, q cho giá trị lớn Phương pháp dựa việc tính hàm băm cho vị trí i văn bản, cho trước giá trị ví trí i-1 nó, suy hoàn toàn trực tiếp từ công thức toán học Giả sử ta dịch M ký tự thành số cách nén chúng lại với từ (word) máy, mà ta xem số nguyên Điều ứng với việc ghi ký tự số hệ thống số d, d số ký tự có Vì số ứng với a[i i+M-1] x = a[i]dM-1 + a[i+1]dM-2 + …+ a[i+M-1]d0 Và giả sử ta biết giá trị h(x) = x mod q Nhưng dịch vị trí sang phải văn tương ứng với việc thay x (x - a[i]dM-1)d + a[i+M] Một tính chất phép toán mod ta thực lúc phép toán nhận câu trả lời Cách khác, ta lấy phần dư chia cho q sau phép toán số học (để giữ cho số mà ta gặp nhỏ), ta nhận câu trả lời thể ta thực tất phép toán học, sau lầy phần dư chia cho q 3.3 Phép đối sánh mẫu Rabin-Karp FUNCTION RABINKARP: integer; CONST q=33253586; d = 32; VAR h1, h2, dM, i: integer; BEGIN dM:= 1; FOR i:=1 TO M-1 DO dM:= (d*dM) MOD q; h1: = 0; FOR i: = TO M DO h1:= (h1*d+index(p[i])) MOD q; h2: = 0; FOR i:= TO M DO h2:= (h2*d + index (a[i])) MOD q; i: = 1; WHILE (h1 h2) AND(i

Ngày đăng: 14/06/2016, 22:16

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan