1. Trang chủ
  2. » Công Nghệ Thông Tin

Tiểu Luận Thuật Toán boyer moore

16 72 0

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

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 16
Dung lượng 387 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Thuật toán BoyerMoore được đưa ra năm 1977 để kiểm tra, tìm kiếm xâu cho một văn bản T1,2,…,n có chiều dài n với mỗi Ti là một kí tự trong bảng chữ cái (alphabet) với kích thước là 256 ký tự khác nhau. và một xâu mẫu P1,2,…,m có chiều dài m (m≤n). Tìm (các) vị trí xuất hiện của xâu P (như là một xâu liên con liên tục) trong văn bản T. Như vậy, thuật toán BoyerMoore sẽ đối sánh T và P theo chiều từ phải sang trái của P. Bằng cách áp dụng thêm luật kí tự tồi (bad character rule) và luật hậu tố tốt.

Trang 1

MỤC LỤC

MỤC LỤC 1

I – GIỚI THIỆU 2

II- THUẬT TOÁN BOYER MOORE 2

III- SỐ PHÉP GÁN VÀ SO SÁNH 7

IV – ĐỘ PHỨC TẠP CỦA THUẬT TOÁN 10

V- KẾT LUẬN: 13

VI – TÀI LIỆU THAM KHẢO 13

Trang 2

I – GIỚI THIỆU

Thuật toán Boyer-Moore được đưa ra năm 1977 để kiểm tra, tìm kiếm xâu cho một văn bản T[1,2,…,n] có chiều dài n với mỗi T[i] là một kí tự trong bảng chữ cái (alphabet) với kích thước là 256 ký tự khác nhau và một xâu mẫu P[1,2,…,m] có chiều dài m (m≤n) Tìm (các) vị trí xuất hiện của xâu P (như là một xâu liên con liên tục) trong văn bản T

Như vậy, thuật toán Boyer-Moore sẽ đối sánh T và P theo chiều từ phải sang trái của P Bằng cách áp dụng thêm luật kí tự tồi (bad character rule) và luật hậu tố tốt

II- THUẬT TOÁN BOYER MOORE

1 Luật kí tự tồi:

Xuất hiện sự khác nhau giữa mẫu P và văn bản T: b = T [i+ j]# P[ i]=,

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+ j]= b để đả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

Trước hết chúng ta hãy xem xét ví dụ sau để hiểu luật này

T=FINDIFAHAYXEACKNEXDLET=FINDIFAHAYXEACKNEXDLE P=NEXDLEP

Tại bước đầu tiên (i=1)so sánh T[1,2,…,6] với P[1,2,…,6] ta thấy rằng T[6]≠P[6] (chú ý ta so sánh từ phải sang trái của P) Do T[6]∉P, ta ngay lập tức có thể dịch P lên 6 đơn vị và bắt đầu so sánh T[7,8,…,12] với P[1,2,

…,6]

Trang 3

Tại bước này ta sẽ gặp vị trí không khớp T[11]≠P[5], vì T[11]=P[3], ta sẽ dịch P lên 2 đơn vị để cho T[11] thẳng hàng với P[3] và tiếp tục so sánh T[9,

…,14] với P[1,2,…,6]

Tại bước này, T[14]≠P[6] và T[14]∉P, ta dịch P lên 6 đơn vị và so sánh T[15,…,20] với P[1,2,…,6]]

Tiếp tục các bước như trong hình vẽ dưới đây, cuối cùng ta tìm được mẫu P ở vị trí i=16

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

N E X D L E

N E X D L E

N E X D L E

N E X D L E

N E X D L E

Hình 1 – Quá trình so khớp mẫu P=”NEXDLE” của thuật toán Boyer-Moore

Luật kí tự tồi: Dịch P lên một số x đơn vị sao cho kí tự tồi T[k] khớp

với kí tự P[s] là kí tự xuất hiện gần với P[m] nhất (s lớn nhất) Nếu s>js>j hoặc không tồn tại kí tự P[s] như vậy thì ta dịch P lên 1

Để thực thi luật kí tự tồi, với mỗi kí tự ∈Σ, gọi R[σ]] là vị trí xuất hiện của kí

tự σ]gần với P[m] nhất Nếu σ]∉P, R[σ]]=0 Theo quy luật kí tự tồi, mỗi bước

chúng ta sẽ dịch P một đoạn là: max(1,j−R[T[k]])

Trang 4

Hình 2 – Quá trình dịch P lên một số x đơn vị

Thủ tục thuật giả mã của thuật toán BM sử dụng luật kí tự tồi như sau:

int BMmatcher(int n, int m){

badCharBackup(m);

int i = 1, j = 0, p = 0, skip = 0;

while(i <= n-m+1){

skip = 0;

j = m;

while(j >= 1 && skip == 0){

if(T[i+j-1] != P[j]){

p = T[i+j-1]-96;

skip = max(1, j - R[p]);

}

j ;

Index

x 2

x 1

x 4

x 4

x 4

x 4

Trang 5

}

if(skip == 0) {

return i;

}

i = i + skip;

}

return -1;

}

void badCharBackup(int m){

int i = 0;

memset(R, 0, sizeof(R));

for(i = 1; i <= m; i++){

R[P[i] - 96] = i;

}

}

2 Luật hậu tố tốt (Good suffix rule)

Luật hậu tố tốt chúng ta phát biểu trong phần này mạnh hơn phát biểu gốc cuả thuật toán Boyer-Moore

Luật hậu tố tốt: Giả sử khi so sánh, một xâu con Tsub của văn

bản T khớp với hậu tố của mẫu P, nhưng kí tự liền kề bên trái của Tsub không

khớp với kí tự tương ứng trong P Tìm một xâu con tsub (nếu có) phải nhất (right most gần với kí tự cuối P[m] nhất) của P thỏa mãn: tsub không phải

là hậu tố của P và kí tự liền kề bên trái của tsub khác với kí tự liền kề bên trái của hậu tố Tsub của P Dịch P sao cho tsub khớp với Tsub trong T.

Nếu tsub không tồn taị, dịch P một số lượng ít nhất sao cho kí tự đầu

tiên của P vượt quá kí tự đầu tiên của Tsub và tiền tố của P khớp với hậu tố

Trang 6

của Tsub Nếu không thể dịch P để thỏa mãn điều kiện đó, dịch P lên m đơn vị

Trường hợp ta tìm tất cả sự xuất hiện của P trong T, sau khi đã tìm thấy P, ta dịch P một lượng ít nhất (> 0) sao cho tiền tố của P khớp với hậu tố của P trong T Trong trường hợp không thể dịch như vậy, dịch P lên m đơn vị

Xét ví dụ sau:

T[1,2,…,30]= C G T G C C T A C T T A C T T A C T T A C T T A C G C G

A A và P[1,2,…,9]= C T T A C T T A C khi so sánh T với P, nhận thấy Tsub={TAC}=T[7,8,9], và cũng tìm được Tsub=(TAC)=P[3,4,5], ta có

thể dịch 4 đơn vị để khớp với Tsub

Hình 3: so sánh P với T theo luật Good suffix rule

Thủ tục thuật giả mã của thuật toán BM sử dụng luật kí tự tồi như sau:

int fastfastBMmatcher(int n, int m){

computeLL(m, LL, Zbar);

computeSL(m, SL, Zbar);

while(i <= n-m+1){

Trang 7

skip = 0;

j = m;

while(j >= 1 && skip == 0){

if(T[i+j-1] != P[j]){

p = T[i+j-1]-96;

skip = max(1, j - R[p]);

if(j!=m){

if(LL[j+1] !=0){

skip = max(skip, m - LL[j+1]); } else {

skip = max(skip, m - SL[j+1]); }

}

}

j ;

}

if(skip == 0) return i;

i = i + skip;

}

return -1;

}

void computeLL(int m, int *LL, int *Zbar){

int i = 0, j = 0;

char Prev[m+1];

int Zrev[m+1];

for(i = m; i >= 1; i ){

Prev[m-i+1] = P[i];

}

compute_Z_function(Prev, Zrev, m);

Trang 8

for(i = 1; i<= m-1; i++){

Zbar[i] = Zrev[m-i+1];

}

for(j = 1; j <= m-1; j++){

i = m - Zbar[j]+1;

LL[i] = j;

}

}

void computeSL(int m, int *SL, int *Zbar){

int i = 1,j = 0;

for(i = 1; i <= m-1; i++){

if(Zbar[i] == i){

SL[m-i+1] = i;

j = i;

} else {

SL[m-i+1] = j;

}

}}

III- SỐ PHÉP GÁN VÀ SO SÁNH

1 Số phép gán

50 113.46 102.25 88.68 82.27 89.72 87.62 102.93 81.98 92.28 98.89

100 100.78 101.11 89.66 83.91 103.99 89.13 101.59 93.30 85.16 93.20

150 102.42 83.28 81.29 87.64 81.33 77.24 79.77 91.12 77.11 73.93

200 89.21 72.92 88.50 88.49 78.86 81.59 70.83 82.85 83.40 79.98

250 46.86 56.74 61.94 58.62 57.62 57.69 59.04 52.55 57.71 59.91

300 70.17 45.83 43.98 55.88 49.93 45.63 49.21 54.75 45.51 50.93

350 29.74 48.35 52.58 55.27 37.43 46.14 49.57 44.64 42.27 46.96

400 49.45 38.34 37.58 29.29 37.24 34.17 38.65 33.43 40.20 34.79

450 45.15 35.15 37.32 34.45 34.95 33.78 34.66 31.41 31.28 35.47

500 19.42 35.95 26.88 34.35 28.60 32.25 36.98 30.35 30.04 31.44

550 22.00 29.21 23.29 29.83 26.24 23.60 23.97 23.91 24.24 23.81

600 21.35 23.71 15.67 21.23 23.26 20.44 21.26 20.53 21.30 21.12

Trang 9

650 14.62 19.93 16.53 20.20 19.26 17.68 17.28 16.74 17.88 17.18

700 20.25 19.13 16.39 19.04 17.31 19.66 19.47 19.06 15.90 18.43

750 15.96 14.85 13.81 14.64 16.13 14.42 15.83 17.53 15.67 15.68

800 13.54 16.57 16.66 15.07 15.41 15.04 16.55 15.56 15.80 16.05

850 17.67 14.15 14.41 15.74 12.79 13.71 14.11 15.30 15.55 15.80

900 15.17 14.59 12.76 14.40 13.88 13.18 15.99 15.78 14.21 14.64

950 14.39 14.72 16.14 13.91 13.69 14.51 14.50 13.66 14.29 14.76

1000 16.71 13.40 14.83 14.65 12.92 14.32 13.23 13.41 13.76 13.78

b Số phép so sánh

50 223.10 201.00 173.85 160.96 175.73 171.63 202.14 160.49 180.96 194.17

100 198.21 198.77 175.76 164.35 204.45 174.77 199.60 183.10 166.82 182.89

150 201.31 162.97 159.14 171.69 159.13 151.02 156.06 178.63 150.75 144.45

200 174.89 142.38 173.32 173.48 154.34 159.60 138.17 162.17 163.27 156.41

250 90.25 109.93 120.45 113.66 111.64 111.96 114.57 101.61 111.93 116.27

300 136.75 88.14 84.42 108.14 96.43 87.70 94.96 105.94 87.52 98.32

350 56.20 93.09 101.64 106.97 71.30 88.81 95.63 85.84 81.06 90.41

400 95.52 73.00 71.66 55.12 70.94 64.81 73.75 63.37 76.86 66.06

450 86.69 66.67 71.05 65.44 66.49 64.01 65.89 59.39 59.08 67.37

500 35.52 68.44 50.14 65.22 53.71 60.96 70.36 57.21 56.51 59.36

550 40.42 54.88 43.11 56.04 49.01 43.70 44.47 44.29 45.00 44.09

600 39.35 43.95 27.94 38.94 42.98 37.39 39.08 37.58 39.16 38.69

650 26.04 36.34 29.54 36.91 34.96 31.81 31.02 29.98 32.17 30.86

700 36.94 34.66 29.38 34.50 31.18 35.73 35.40 34.57 28.35 33.31

750 28.48 26.26 24.17 25.89 28.71 25.42 28.15 31.50 27.84 27.79

800 23.70 29.55 29.71 26.64 27.45 26.60 29.56 27.61 28.10 28.57

850 31.72 24.98 25.37 27.98 22.24 24.00 24.81 27.10 27.60 27.97

900 26.87 25.72 22.02 25.32 24.29 22.90 28.40 28.01 24.90 25.81

950 25.37 26.09 28.70 24.30 23.93 25.41 25.59 23.87 25.13 26.03

1000 29.98 23.39 26.14 25.79 22.37 25.18 23.01 23.35 24.11 24.12

V- KỲ VỌNG, PHƯƠNG SAI, ĐỘ LỆCH CHUẨN, ĐỒ THỊ

5.1 Số phép gán

n Kỳ vọng Phương sai Độ lệch chuẩn Chặn trên Chặn dưới

Trang 10

400 33.315 25.74407222 5.073861668 38.388862 28.24114

Đồ thị biểu diễn

5.2 Số phép so sánh

n Kỳ vọng Phương sai Độ lệch chuẩn Chặn trên Chặn dưới

Trang 11

400 64.628 102.9767067 10.1477439 74.7757439 54.480256

Đồ thị biểu diễn

IV – ĐỘ PHỨC TẠP CỦA THUẬT TOÁN

Xét tổng quát chương trình sau:

int BMmatcher(int n, int m){

int R[28];

int Zbar[MAXM];

int LL[MAXM];

int SL[MAXM];

badCharBackup(m);

Trang 12

int i = 1, j = 0, p = 0, skip = 0;

computeLL(m, LL, Zbar);

computeSL(m, SL, Zbar);

while(i <= n-m+1){

skip = 0;

j = m;

while(j >= 1 && skip == 0){

if(T[i+j-1] != P[j]){

p = T[i+j-1]-96;

skip = max(1, j - R[p]);

if(j!=m){

if(LL[j+1] !=0){

skip = max(skip, m - LL[j+1

} else {

skip = max(skip, m - SL[j+1

}

}

}

j ;

}

if(skip == 0) return i;

i = i + skip;

}

return -1;

}

1 Tính toán độ phức tập của chương trình con

Thực hiện tính toán trên số phép so sánh

Trang 13

void badCharBackup(int m) {

int i = 0;

for (i = 0; i < m; i++) { m+1 lần

R[P[i] - 26] = i;

}

Vậy độ phức tạp O(m+1)

2 Tính toán độ phức tạp của chương trình con

Thực hiện tính toán trên số phép so sánh

void computeLL(int m, int *LL, int *Zbar){

for(i = 1; i<= m-1; i++){ m lần

Zbar[i] = Zrev[m-i+1];

}

for(j = 1; j <= m-1; j++){ m lần

i = m - Zbar[j]+1;

LL[i] = j;

}

}

Thực hiện tính toán trên số phép so sánh

void computeSL(int m, int *SL, int *Zbar){

int i = 1,j = 0;

for(i = 1; i <= m-1; i++){ m lần

if(Zbar[i] == i){ m lần

SL[m-i+1] = i;

j = i;

} else {

SL[m-i+1] = j;

}

Trang 14

}

} Vậy ta tính được độ phức tạp của chương trình trên là O(4m) 3 Tính độ phức tạp trong chương trình chính Thực hiện tính toán trên số phép so sánh BOYERMOORE (int n, int m){ while(i <= n-m+1){ n-m+2 skip = 0; j = m; while(j >= 1 && skip == 0){ m(n-m+2)+1 if(T[i+j-1] != P[j]){ m(n-m+2) p = T[i+j-1]-96; skip = max(1, j - R[p]); if(j!=m){ m(n-m+2) if(LL[j+1] !=0){ m(n-m+2) skip = max(skip, m - LL[j+1 } else { skip = max(skip, m - SL[j+1

}

}

}

j ;

}

if(skip == 0) return i; m(n-m+2)

i = i + skip;

Trang 15

}

}

Vậy ta tính được độ phức tạp là O(n-m+1 +m(n-m+1)+1+4(m(n-m)))

=O(5(m(n-m)+n+1)

Tổng kết lại ta có: O (m+1) +O(4m)+ O(5(m(n-m)+n+1)

Kết luận: vậy độ phức tạp của thuật toán là O(m*n)

V- KẾT LUẬN:

Thuật toán Boyer Moore là thuật toán tìm kiếm chuỗi rất có hiệu quả trong thực tiễn, các dạng khác nhau của thuật toán này thường được cài đặt trong các chương trình soạn thảo văn bản

Các đặc điểm chính của nó: Thực hiện việc so sánh từ phải sang trái Giai đoạn tiền xử lý (preprocessing) có độ phức tạp thời gian và không gian là O(m +C) Giai đoạn tìm kiếm có độ phức tạp lớn nhất O(m*n)

Thuật toán Boyer-Moore có thể đạt tới chi phí O(n/m) là nhờ có cách dịch thứ 2 “ký tự không khớp” Cách chuyển cửa sổ khi gặp “ký tự không khớp” cài đặt vừa đơn giản lại rất hiệu quả trong các bảng chữ cái lớn nên có nhiều thuật toán khác cũng đã lợi dụng các quét mẫu từ phải sang trái để sử dụng cách dịch này

Tuy nhiên có một vài thuật toán đã cải tiến cách dịch này để đưa đến chi phí tính toán của thuật toán Boyer-Moore là tuyến tính như: BMH (BM-Horspool) [1] đưa ra năm 1980 dùng cho tập đơn mẫu CW (Commentz & Walter) [10] đưa ra năm 1979, SBMH [11] năm 2002 và YBHK [12] năm

2003, WM (Wu & Manner) năm 1994 dùng cho tập đa mẫu Với CW thì độ phức tạp thời gian trong trường hợp tốt nhất với tập p mẫu là: O(n*max{m[0], m[1], m[p-1]}) còn trong trong trường hợp tốt nhất thời gian thực thi là O(n/ min{m[0], m[1], m[p-1]}) với m[i] là độ dài của mẫu thứ i

Trang 16

VI – TÀI LIỆU THAM KHẢO

[1] Boyer, Robert S., and J Strother Moore A fast string searching algorithm Communications of the ACM 20.10 (1977): 762-772

Ngày đăng: 19/07/2020, 20:12

TỪ KHÓA LIÊN QUAN

w