Đõy là thuật toỏn đối sỏnh mẫu cú hiệu quả trong nhiều ứng dụng, nú là lừi của cỏc lệnh tỡm kiếm và thay thế trong cỏc trỡnh soạn thảo văn bản. Tiến trỡnh xử lý duyệt văn bản của thuật toỏn này từ phải sang trỏi, thay vỡ duyệt từ trỏi sang phải như cỏc thuật toỏn khỏc. Trong khi đối sỏnh, thuật toỏn sử dụng hai hàm để dịch vị trớ đang xột trong văn bản. Hai hàm dịch đú gọi là Better_factor và Bad_symbol,
mục đớch hai hàm này và cỏch tớnh giỏ trị của chỳng được trỡnh bày sau.
Giả sử p là vị trớ đang xột trờn văn bản và cú sự khụng trựng khớp giữa mẫu và văn bản là ký tự nằm giữa y[p+i] và x[i] với 0 i < m.
Tức là: y[p+i]x[i]
Và y[p+i+1..p+m-1] = x[i+1..m-1]
Hàm dịch Better_factor dóy cỏc ký tự y[p+i+1..p+m-1] khớp với những ký
tự phải nhất trong mẫu x là x[k+1..m-1-i+k] và thụng bỏo rằng ký tự x[k] khụng khớp ký tự x[i] để trỏnh sự khụng trựng khớp. Nếu khụng cú nhiều sự khụng trựng
khớp như thế thỡ hàm dịch chứa hậu tố dài nhất là
y[p+i+1..p+m-1] tương ứng với tiền tố của x.
Hàm dịch Better_factor được xỏc định như sau:
[i]=min{i-k|(0k<i,x[k+1..m-1-i+k]=x[i+1..m-1], x[k]x[i]
or (i-mk<0,x=x[i-k..m-1]x[m-i+k..m-1]} với i[0,1, .. , m-1]
Giỏ trị [i] là độ dài chớnh xỏc mà cú thể dịch do hàm Better_factor tớnh được và thời gian thực hiện hàm này O(m)
Better_factor_function(x,m) [11] for j = 0 to m-1 // từ 0 đến m-1
[j] 0 i 0
65 for j = m-1 downto 0
{
f[j] i +1
while (i<m) and (x[j] x[i]) { if ( [j] = 0) [j] i-j i f[i] -1 } i i-1 } for j = 0 to m-1 { if ([j] = 0) [j] i + 1 if (j = i) i f[i] -1 } return ()
Bõy giờ xột đến hàm Bad_factor, xột ký tự y[p+i] là ký tự khụng khớp trong văn bản. Giả sử y[p+i] cú mặt trong x[0..m-2] và vị trớ phải nhất mà nú xuất hiện là
k, vậy khung nhỡn văn bản cú thể dịch đi i-k vị trớ sang phải nếu k<i, ngoài ra chỉ cú
thể dịch một vị trớ để trỏnh sự bỏ qua sự xuất hiện của mẫu. Giả sử y[p+i] khụng
xuất hiện trong x thỡ bỏ qua vị trớ p+i trong văn bản. Xột một chỉ mục trờn tập ký
tự chữ cỏi và mỗi ký tự a được định nghĩa: [a] = min{m} { m-1-j | 0 j < m-1, x[j] = a}
Giỏ trị Bad_symbol của một ký tự tại vị trớ i trong mẫu cú giỏ trị như sau: [a,i] = max {[a] +i-m+1, 1}
Hàm sau tớnh giỏ trị của bảng , thời gian thực hiện là O(m+card). Last_occurrence_function(x,m) [11]
66 [a] m
for j = 0 to m-2
[x[j]] m-1-j return ()
Khi thực hiện dịch khung nhỡn, thuật toỏn Boyer_Moore chọn giỏ trị dịch lớn hơn trong hai giỏ trị do hàm Better_factor và hàm Bad_symbol tớnh được. Nếu tỡm
thấy sự trựng khớp mẫu thỡ thụng bỏo và dịch đi [0] vị trớ để tiếp tục đối sỏnh cho đến hết văn bản. Boyer_Moore_Matcher(x,m,y,n) [11] Better_factor_function(x,m) Last_occurrence_function(x,m) p 0 while (p n-m) { i m- 1
while (i 0) and (y[p+i] = x[i]) i i-1 if (i 0) p p+max{[i], [y[p+i]]+i-m+1} else { output (p) p p + [0] }
Đỏnh giỏ thuật toỏn: Trong trường hợp xấu nhất, thời gian thực hịờn thuật
toỏn này là O(m*n), trong trường hợp chỉ tỡm một vị trớ xuất hiện đầu tiờn của mẫu thỡ thuật toỏn chỉ thực hiện với thời gian tuyến tớnh. Điểm mạnh để giảm thời gian tớnh toỏn của thuật toỏn này là giai đoạn tiền xử lý mẫu. Thuật toỏn này rất cú hiệu quả, thực hiện nhanh với tập ký tự chữ cỏi lớn.
Hàm tớnh giỏ trị Bad_symbol được giới thiệu trong thuật toỏn Boyer_Moore cú hiệu quả khụng cao khi xử lý mẫu cú tập ký tự chữ cỏi nhỏ, ngược lại nếu số lượng ký tự trong tập chư cỏi khỏ lớn thỡ việc đối sỏnh mẫu trở nờn rất hiệu quả.
67
Xột vị trớ p trờn khung nhỡn vào văn bản, giả sử rằng ký tự y[p+m-1] và x[m-
1] đồng nhất với nhau. Nếu x[m-1] khụng xuất hiện trong tiền tố x[0.. m-2] của mẫu x thỡ khung nhỡn cú thể dịch sang phải m vị trớ, sau đú thực hiện đối sỏnh
chuỗi ký tự y[p..p+m-2] với x[0..m-2]. Nếu khụng, k là vị trớ xuất hiện phải nhất
của ký tự x[m-1] trong chuỗi x[0..m-2] thỡ khung nhỡn cú thể dịch sang phải m-1-k
vị trớ. Điều này cho thấy rằng [y[p+m-1]] cũng là giỏ trị cú thể dịch trong trường
hợp y[p+m-1]=x[m-1]. Điều này thể hiện trong thuật toỏn Horspool sau. Thuật toỏn đối sỏnh mẫu Horspool:
Horspool_Matcher(x,m,y,n) [11] Last_occurence_function(x,m) t [x[m-1]] [x[m-1]] 0 j m-1 while (j <n) { s [y[j]] if (s 0) j j + s else { if y[j-m+1..j-1] = x[0..m-2] output (j-m+1) j j + t } }
Nhận xột: Thuật toỏn Horspool thực hiện trong thời gian O(m*n), nhưng
trong thực tế thỡ tốt hơn thuật toỏn Boyer_Moore.