Tải bản đầy đủ (.doc) (18 trang)

Tiểu luận môn phân tích và đánh giá thuật toán bài toán đối sánh mẫu thuật toán boyer moore

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (196.08 KB, 18 trang )

KHOA CÔNG NGHỆ THÔNG TIN
******

*****

BÁO CÁO BÀI TẬP LỚN MÔN HỌC
PHÂN TÍCH VÀ ĐÁNH GIÁ THUẬT TOÁN
Đề bài: Bài toán đối sánh mẫu. Thuật toán Boyer - Moore

Giáo viên hướng dẫn

: PGS.TS. Đào Thanh Tĩnh

Học viên thực hiện

: Bùi Thị Thao

Lớp

: HTTT – K25B

Hà Nội, tháng 5/2014

1


MỤC LỤC
PHẦN 1: KHÁI NIỆM CƠ BẢN VỀ ĐỐI SÁNH XÂU KÍ
TỰ
3
1.1. Giới thiệu........................................................................................................3


1.3.Thuật toán đối sánh chuỗi kí tự đơn giản......................................................4
1.3.1.Thuật toán.................................................................................................4
1.3.2.Mô tả thuật toán........................................................................................4
1.3.3.Ví dụ mô phỏng thuật toán........................................................................4
1.3.4.Phân tích thuật toán..................................................................................6
PHẦN 2: CÁC THUẬT TOÁN ĐỐI SÁNH XÂU KÍ TỰ.....8
2.1. Thuật toán Knuth – Morris – Pratt (KMP)...................................................8
2.1.1. Ý tưởng thuật toán....................................................................................8
2.1.2. Phát biểu thuật toán.................................................................................8
2.1.3. Ví dụ mô phỏng thuật toán.......................................................................9
2.1.4.Đánh giá độ phức tạp của thuật toán.....................................................12
2.2. Thuật toán Boyer – Moore (BM).................................................................12
2.2.1.Ý tưởng thuật toán...................................................................................12
2.2.2.Thuật toán BM........................................................................................14
2.2.3. Ví dụ mô phỏng thuật toán.....................................................................16
2.2.4. Đánh giá độ phức tạp của thuật toán....................................................18

2


PHẦN 1: KHÁI NIỆM CƠ BẢN VỀ ĐỐI SÁNH XÂU KÍ TỰ
1.1. Giới thiệu
Ngày nay, với sự phát triển của Công nghệ thông tin, máy tính đã thâm nhập vào
tất cả các lĩnh vực của xã hội. Việc số hóa dữ liệu, lưu trữ và xử lý các văn bản trên máy
tính là một việc làm hết sức quan trọng.
Trong các hệ xử lý văn bản chuỗi ký tự được coi là thành phần trung tâm, các hệ
xử lý văn bản cung cấp nhiều thuật toán đóng vai trò quan trọng trong việc thao tác trên
các chuỗi ký tự. Một phép toán cơ bản trên chuỗi ký tự là đối sánh chuỗi ký tự (String
Matching). Cho trước một chuỗi văn bản T có độ dài n và một mẫu P có độ dài m, hãy tìm
sự xuất hiện của mẫu P trong văn bản T.

Bài toán đối sánh chuỗi ký tự có thể được đặc trưng như một bài toán tìm kiếm,
trong đó mẫu P được xem như khoá, tuy nhiên các thuật toán tìm kiếm thông thường
không áp dụng được một cách trực tiếp vì mẫu P có thể dài và nó trải trên văn bản theo
một cách không biết trước được. Đây là một bài toán thú vị có nhiều thuật toán khác nhau
như Brute-Force (BF), Knuth-Morris-Pratt (KMP), Boyer-Moore (BM), Karp- Rabin
(KR), …
1.2. Bài toán
Giả sử chúng ta có một văn bản T là một mảng có độ dài là n (T[1...n]) và một
chuỗi mẫu P có độ dài là m (P[1...m]) (điều kiện m<=n). Các phần tử của T và P là các ký
tự trong tập hữu hạn alphabet Σ. VD: Σ = {0,9} hoặc Σ = {a,b,c...,z,A,B,C,…,Z}. Mảng
ký tự P và T được gọi là chuỗi ký tự.
Bài toán: P ⊆ T ?
Nếu P ⊆ T: Xác định vị trí xuất hiện đầu tiên của P trong T?
Khi đó bài toán đối sánh chuỗi được phát biểu như sau: Cho một chuỗi T ban
đầu và một chuỗi mẫu P. Đối sánh chuỗi ký tự chính là việc tìm chuỗi mẫu P trong chuỗi
T ban đầu. Nếu chuỗi mẫu P được tìm thấy trong chuỗi T ban đầu hãy chỉ ra vị trí trong T
mà tại đó chuỗi mẫu P được tìm thấy.

3


1.3. Thuật toán đối sánh chuỗi kí tự đơn giản
1.3.1. Thuật toán
- Input:

P[1..m], T[1..n];

- Output: i0 (if P ≡ T[i0.. i0+m-1], i0 ≥1, ngược lại i0=0)
a) i=1; j= i; k=1;
b) while (j≤n) & (k≤m)

if (T(j) = P(k))
{ j++; k++; }
else
{ i++; j=i; k=1;}
c) if (k>m) i0 := i;
else

i0 :=0;

1.3.2. Mô tả thuật toán
Thuật toán thực hiện như sau: Tiến hành so sánh phần tử thứ nhất của chuỗi mẫu P
với phần tử thứ nhất của chuỗi ban đầu T. Nếu hai phần tử này giống nhau, tiến hành so
sánh tiếp phần tử thứ 2. Cứ như vậy cho đến khi tìm được chuỗi P trong T hoặc phát hiện
ra vị trí mà tại đó phần tử của T và P khác nhau.
Trong trường hợp phát hiện ra vị trí mà tại đó phần tử của T và P khác nhau ta tiến
hành dịch phải chuỗi P đi một phần tử so với chuỗi T. Lặp lại thao tác so sánh như trên
cho đến khi đạt được kết quả, hoặc không tìm thấy nếu duyệt hết chuỗi T.
1.3.3. Ví dụ mô phỏng thuật toán
Giả sử cho chuỗi T = “ABCABCDABABCDA1DA1BDA”
Chuỗi P = “ABCDA1”
Tiến hành thực hiện thuật toán đối sánh mẫu đơn giản qua các bước như sau:

4


 Bước 1:
i:

1


T: A B C A B C D A B
j:

A

B

C

D

A

1

D

A

1

B

D

A

1

P: A B C D A 1

k:

1
 n = 21
 m =6
 i=1, j=1, k=1 ta có T[1] = P[j] tăng j = j+1= 2 và k = k+1 = 2 để tiếp tục so
sánh.

 Bước 2:
i:

1

T: A B C A B C D A B
j:

1

A

B

C

D

A

1


D

A

1

B

D

A

2

P: A B C D A 1
k:

1

2
 i =1, j=2, k= 2 ta có T[2] = P[2] tăng j = j+1 =3 và k = k+ 1=3 để tiếp tục so
sánh.

 Bước 3:
i:

1

T: A B C A B C D A B A
j:


1

2

B

C

D

A

1

D

A

1

B

D

A

3

P: A B C D A 1

k: 1

2

3

 i = 1, j= 3, k = 3 ta có T[3] = P[3] tăng j =j+1 =4 và k = k+ 1= 4 để tiếp tục so
sánh.
 Bước 4:
i:

1

T: A B C A B C D A B

A

B

C

D

A

1

D

A


1

B

D

A

5


j:

1

2

3

4

P: A B C D A 1
k: 1

2

3

4


 i = 1, j = 4, k = 4 ta có T[4] <> P[4] tăng i = i+1 =2 (dịch chuỗi P sang phải 1
vị trí so với T để tiếp tục so sánh), gán j = i =2, k=1.
 Bước 5:
i:

1

2

T: A B C A B C D A B
j:

2

P:

A B C D A 1

k:

1

A

B

C

D


A

1

D

A

1

B

D

A

 j=2, k =1 ta có T[2] <> P[1] tăng i = i+1 =3 ( dịch chuỗi P sang phải 1 vị trí so
với T để tiếp tục so sánh), gán j = i = 3, k =1 và bắt đầu so sánh.
Cứ như vậy lặp đi lặp lại các bước của thuật toán đối sánh chuỗi. Sau 9 lần dịch phải
chuỗi P so với chuỗi T ta thu được kết quả như sau:
i:

1

2

3

4


5

6

7

8

9 10

T: A B C A B C D A B

A

B

C

D

A

1

A

B

C


D

A

1

D

A

1

B

D

A

j:
P:
k:
Kết quả tìm được vị trí xuất hiện đầu tiên của P trong T là 10
1.3.4. Phân tích thuật toán
Việc tiến hành theo đúng các bước của thuật toán đối sánh chuỗi như trên sẽ trả
cho ta kết quả xem có tìm thấy chuỗi mẫu P trong chuỗi T ban đầu hay không. Nếu chuỗi
mẫu P được tìm thấy thì tìm thấy ở vị trí phần tử nào trên chuỗi T.
Tuy nhiên thuật toán đối sánh chuỗi này còn gặp nhược điểm lớn về thời gian thực
hiện thuật toán như sau:
- Với n là độ dài của chuỗi T ban đầu, m là độ dài của chuỗi mẫu P thì thời gian so

khớp hai chuỗi là O(mn). Đây là một thời gian lớn làm cho thuật toán có tốc độ chậm.

6


- Nguyên nhân của việc chậm này là do việc so sánh các phần tử của chuỗi T được
thực hiện lặp đi lặp lại n lần trong những lần so sánh tiếp theo. Và tại mỗi vị trí i trong T
ta so sánh m ký tự trong P. Như vậy trong trường hợp xấu nhất sẽ có mn phép so sánh.
Như vậy độ phức tạp thuật toán là O(mn).
Trong ví dụ đã nêu ở trên việc so sánh hai phần tử ở vị trí tương ứng của hai chuỗi
T và P phát hiện ra vị trí khác nhau đầu tiên sau 4 lần so sánh, tức là T[4] và P[4] khác
nhau. Theo đúng thuật toán chuỗi mẫu P sẽ dịch sang phải so với chuỗi T một vị trí và
việc so sánh lại bắt đầu lại từ đầu. Mặc dù trong lần so sánh trước đã biết giá trị T[1] và
biết T[1] khác P[1]. Đây là việc làm lặp đi lặp lại đối với T[1] trong các lần so sánh tiếp
theo, làm tăng thời gian thực hiện thuật toán.
Như vậy chúng ta thấy thuật toán đối sánh chuỗi ký tự đơn giản không phải là một
thuật toán tối ưu. Vì vậy cần xem xét đến một phương án tối ưu hơn, có thời gian thực
hiện thuật toán nhỏ hơn.

7


PHẦN 2: CÁC THUẬT TOÁN ĐỐI SÁNH XÂU KÍ TỰ
2.1. Thuật toán Knuth – Morris – Pratt (KMP)
2.1.1. Ý tưởng thuật toán
Tư tưởng cơ bản của thuật toán Knuth-Morris-Pratt (KMP) là thay vì ta so sánh
mẫu với lần lượt từng vị trí trong văn bản thì ta dựa vào các ký tự đã biết trước trong mẫu
để làm sao giảm được số các phép so sánh. Cụ thể là khi phát hiện ra có sự không khớp
giữa hai chuỗi, ta không gán i như trong thuật toán đối sánh chuỗi ở trên để dịch chuyển
mẫu sang phải một bước để tiếp tục so sánh với văn bản T, mà chúng ta tìm cách để dịch

chuyển mẫu với số đơn vị lớn hơn hoặc bằng 1, và giảm số ký tự phải so sánh lại.
Ví dụ: Nếu mẫu có dạng là một xâu nhị phân có dạng đặc biệt là BAAAAAAA (ký
tự đầu tiên của mẫu chỉ xuất hiện 1 lần). Khi đó giả sử có một khởi đầu sai dài i ký tự (tức
là i ký tự đầu tiên của mẫu là khớp với một đoạn nào đó trong văn bản T ). Như vậy nếu
ký tự thứ i+1 là không khớp thì ta biết rằng i ký tự trước trong mẫu đã khớp nhau rồi.
Điều đó có nghĩa là i ký tự này có dạng ở cả trong mẫu lẫn văn bản. Một điều hiển nhiên
là ta không phải so sánh ký tự thứ nhất của mẫu P[1] với i-1 ký tự tiếp theo trong văn bản,
hay nói cách khác dịch chuyển mẫu sang i đơn vị gán lại (gán lại j=1 còn i vẫn giữ
nguyên). Để so sánh kí tự đầu tiên của mẫu với ký tự thứ i trong văn bản.
Tuy nhiên trong thực tế hầu như không xảy ra trường hợp đặc biệt như vậy, và
thuật toán KMP là sự tổng quát hóa từ tư tưởng đó.
2.1.2. Phát biểu thuật toán
Trước hết chúng ta cần xây dựng một mảng tiền tố next[1..m] để xác định xem
phải dự phòng một khoảng bao nhiêu khi phát hiện sự không ăn khớp của mẫu P với T.
Chúng ta dịch chuyển một bản sao j-1 ký tự đầu tiên của mẫu trên chính nó từ trái sang
phải; bắt đầu từ ký tự đầu tiên của bản sao trên ký tự thứ hai của mẫu và ngừng lại khi các
ký tự các khớp nhau, hay không có ký tự nào khớp nhau cả. Khoảng cách để dự phòng
trong mẫu next[j] được xác định chính xác là cộng 1 với số các ký tự gối khớp nhau. Đặc
biệt là một số j>1 thì giá trị của next[j] là số k lớn nhất mà nhỏ hơn j sao cho k-1 ký tự
đầu tiên của bản sao khớp với k-1 ký tự cuối cùng trong j-1 ký tự đầu tiên trong mẫu. Mặt
khác chúng ta cũng định nghĩa next[1] = 0. Ta có thuật toán tính mảng next như sau:
 Thuật toán: Tính mảng tiền tố next

8


Next [1…m]
Next[1] = 0;
For k=1 to m do
t=Next[k];

while (t>0) & (Pt<>Pk)
t = Next[t];
Next[k+1] = t+1;
 Thuật toán: Tìm vị trí mẫu P trong T với KMP
Input: chuỗi mẫu P và chuỗi văn bản gốc T, next là mảng tiền tố lưu khoảng dự phòng
cho bước nhảy.
Output: vị trí tìm thấy của sâu P trong chuỗi văn bản T, nếu vị trí đó >n thì không tìm
thấy.
Input: P[1…m], T[1…n];
Output: i0 (if P ≡ T[i0……. i0+m-1] , i0 ≥ 1, ngược lại i0=0)
a) k:=1; j:=1;
b) while(j<=n) & (k<=m)
if (k=0) or (T[j]=P[k])
{ j++; k++; }
else
k=Next(k);
c) if(k>m) i0 :=j - m;
else

i0 :=0;

2.1.3. Ví dụ mô phỏng thuật toán
Giả sử cho chuỗi văn bản T = “ABCABCDABCDA1ABDA1BA”
Chuỗi mẫu P = “ABCDA1”
Trước hết ta xây dựng mảng Next[1…m] cho mẫu P = “ABCDA1”

9


K


1

2

3

4

5

6

P

A

B

C

D

A

1

Next [k]

0


1

1

1

1

2

7
1

Tiến hành thực hiện thuật toán KMP qua các bước như sau:
-

Với m=6, n=20, k=1, j=1
T[1] = P[1], k=k+1, j=j+1
T:

A B C A B C D A B C D A 1 A B D A 1 B A

j

1 2

k

1 2


P:

A B C D A 1

T[2] = P[2], k=k+1, j=j+1
T:

A B C A B C D A B C D A 1 A B D A 1 B A

j

1 2 3

k

1 2 3

P:

A B C D A 1

T[3] = P[3], k=k+1, j=j+1
T:

A B C A B C D A B C D A 1 A B D A 1 B A

j

1 2 3 4


k

1 2 3 4

P:

A B C D A 1

T[4]≠P[4], k≠0: k=Next[k]=Next[4]=1

T:
j

A B C A B C D A B C D A 1 A B D A 1 B A
1 2 3 4

10


k

1

P:

A B C D A 1
T[4] = P[1], k=k+1, j=j+1

T:


A B C A B C D A B C D A 1 A B D A 1 B A

j

1 2 3 4 5

k

1 2

P:

A B C D A 1

T[5] = P[2], i=i+1, j=j+1
T[6] = P[3], k=k+1, j=j+1
T[7] = P[4], k=k+1, j=j+1
T[8] = P[5], k=k+1, j=j+1
T:

A B C A B C D A B C D A 1 A B D A 1 B A

j

1 2 3 4 5 6 7 8 9

k

1 2 3 4 5 6


P:

A B C D A 1

T[9]≠P[6], k = Next[6] = 2
T:

A B C A B C D A B C D A 1 A B D A 1 B A

j

1 2 3 4 5 6 7 8 9

k

2

P:

A B C D A 1

T[9] = P[2], i=i+1, j=j+1
T[10] = P[3], k=k+1, j=j+1
T[11] = P[4], k=k+1, j=j+1
T[12] = P[5], k=k+1, j=j+1
T[13] = P[6], k=k+1, j=j+1
T:
j


A B C A B C D A B C D A 1 A B D A 1 B A
1 2 3 4 5 6 7 8 9 10 11 12 13 14

11


k

2 3 4 5 6 7

P:

A B C D A 1

Với j=14, k=7> 6=m ta có: i0= j-m=14-6=8. Vậy vị trí xuất hiện đầu tiên của mẫu P
trong T là 8
Tương tự ta xét tiếp xem P có xuất hiện ở vị trí nào khác trong T nữa không.
T:

A B C A B C D A B C D A 1 A B D A 1 B A

j

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

k

1 2 3

P:


A B C D A 1

Output: i0=8 (tức là chuỗi P xuất hiện 1 lần trong T tại vị trí 8)
2.1.4. Đánh giá độ phức tạp của thuật toán
Đối với thuật toán tính mảng next, vòng lặp thực hiện đúng m bước lặp, việc gán giá
trị trước đó chỉ thực hiện 1 lần. Vì vậy thuật toán sinh mảng tiền tố Next[..] sẽ có độ
phức tạp là O(m).
Đối với thuật toán KMP: trong trường hợp xấu nhất, không tìm thấy mẫu P thì vòng
lặp phải thực hiện đúng n bước lặp. Thời gian chạy của vòng lặp tìm kiếm sẽ là: O(n).
⇒ Độ phức tạp của giải thuật KMP sẽ là O(m+n) tốt hơn so với giải thuật thông thường
với độ phức tạp là O(m.n)
2.2. Thuật toán Boyer – Moore (BM)
2.2.1. Ý tưởng thuật toá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.
Thuật toán Boyer-Moore kiểm tra các ký tự của mẫu từ phải sang trái và khi phát
hiện sự khác nhau đầu tiên, thuật toán sẽ tiến hành bước nhảy. Trong thuật toán này có
hai trường hợp của bước nhảy

12


Trường hợp 1: Gần giống như cách dịch trong thuật toán KMP, dịch sao cho những
phần đã so sánh trong lần trước khớp với những phần giống nó trong lần
sau.

 Trong lần kiểm tra tại vị trí j, khi so sánh đến ký tự i trên mẫu thì phát hiện ra
sự


khác

nhau,

lúc

đó

P[i+1…m]

=

T[i+j...j+m-1]

=

u



a = P[i]≠ T[i+j-1] = b khi đó thuật toán sẽ tiến hành bước nhảy sao cho đoạn u
= T[i+j…j+m-1] giống với một đoạn mới trên mẫu (trong các bước nhảy ta
chọn bước nhảy nhỏ nhất)

T
P

b
a


u

c

u

P

u

bước nhảy

Dịch chuyển sao cho u xuất hiện lại và c ≠ a
 Nếu không có một đoạn nguyên vẹn của u xuất hiện lại trong P, ta sẽ chọn sao
cho phần đôi dài nhất của u xuất hiện trở lại ở đầu mẫu.

u

b

T

u

a

P

P


bước nhảy

u

Dịch chuyển để một phần đôi của u xuất hiện lại trên x
Trường hợp 2: Coi ký tự đầu tiên không khớp trên văn bản là b=T[i+j-1] ta sẽ
dịch sao cho có một ký tự giống b trên xâu mẫu khớp vào vị trí đó (nếu
có nhiều vị trí xuất hiện b trên xâu mẫu ta chọn vị trí phải nhất)

T

b
a

P
P

b

u
u

bước nhảy
không chứa b

13


Dịch chuyển để ký tự b ăn khớp với văn bản.


 Nếu không có ký tự b nào xuất hiện trên mẫu ta sẽ dịch mẫu sao cho ký tự trái
nhất của mẫu vào vị trí ngay sau ký tự T[i+j-1]=b để đảm bảo sự ăn khớp

T
P

b
a
P

u
u

dịch chuyển
không chứa b

Dịch chuyển khi b không xuất hiện trong x
Trong hai cách dịch thuật toán sẽ chọn cách dịch có lợi nhất.
Trong cài đặt ta dùng mảng bmGs để lưu cách dịch 1, mảng bmBc để lưu phép
dịch thứ 2 (ký tự không khớp). Việc tính toán mảng bmBc thực sự không có gì nhiều để
bàn. Nhưng việc tính trước mảng bmGs khá phức tạp, ta không tính trực tiếp mảng này
mà tính gián tiếp thông qua mảng suff.
Có suff[i]=max{k|x[i-k+1…i]=x[m-k+1…m]}
2.2.2. Thuật toán BM
 Khởi tạo mảng bmBc
procedure initBmBc (P:String);
begin
m = length (P);
1.


for i := 0 to 255 do bmBc[i] := m;

2.

for i := 1 to m - 1 do bmBc[Ord(P[i])] := P.length - i;

end;
procedure suffixes (P:String);
var
right, left, i: integer;
begin
m = length (P);

14


1.

suff[m] := m;
left := m;

2.

for i := m - 1 downto 1 do
if (i > left) and (suff[i + m - right] < i - left) then
suff[i] := suff[i +m - right]
else
a.


if (i < left) then left := i;

b.

right := i;

c.

while (left >= 1) and (X[left] = X[left + m - right]) do
left := left-1;

d.

suff[i] := right - left;

end;
 Khởi tạo mảng bmGs
procedure initBmGs(P:String);
begin
m = length (P);
1.

suffixes(P);

{Tính mảng suff}

2.

for i := 1 to m do
bmGs[i] :=m;


3.

j := 0;

4.

for i := m downto 0 do
if (i = 0) or (suff[i] = i) then
while (j < m - i) do
begin
{Nếu bmGs[j] chưa có giá trị thì điền vào}
if bmGs[j] = m then
bmGs[j] := m - i;
j := j+1 ;
end;

5.

for i := 1 to m - 1 do

15


bmGs[m - suff[i]] := m - i; {đảo lại}
end;
 Thuật toán BM
procedure BM(P,T:String);
var
i, j: integer;

bmBc, bmGs: IndexArray;
begin
1.

initBmBc(P);
initBmGs(P);
j := 1;

2.

while (j <= T.length – P.length + 1) do
2.1

i := P.length;

2.2

while (i >= 1) and (P[i] = T[i + j - 1]) do i:=i-1;

2.3

if (i < 1) then
a.

Output(j);

b.

j := j + bmGs[1];


else

{chọn cách dịch được lợi nhất }
j := j + Max(bmGs[i], bmBc[Ord(T[i + j - 1])] - m + i);

end;
2.2.3. Ví dụ mô phỏng thuật toán
Cho 2 chuỗi ký tự
T = “HCATCHCAHAHAHTATACAHTACH”
P = “HCAHAHAH”
Khởi tạo mảng:
c

A

C

H

T

bmBC[c]

1

6

2

8


16


i

1

2

3

4

5

6

7

8

P[i]

H

C

A


H

A

H

A

H

suff[i]

1

0

0

2

0

4

0

8

bmGs[i]


7

7

7

2

7

4

7

1

Mô tả thuật toán
Bước 1
T


H CA T CHCAHAHAH T A T ACAHT ACH
1

P

HCAHAHAH
Bước nhảy = 1 (bmGs[7]=bmBc[A]-8+8)

Bước 2

T


H CA T CHCAHAHAH T A T ACAHT ACH
3 2 1

P

HCAHAHAH
Bước nhảy = 4 (bmGs[5]=bmBc[C]-8+6)

Bước 3

T

H CA T CHCAHAHAHT A T ACAHT ACH
8 7 6 5 4 3 2 1

P

HCAHAHAH
Bước nhảy = 7 (bmGs[0])

Bước 4
T


H CA T CHCAHAHAHT A T ACAHT ACH

17



3 2 1
P

HCAHAHAH
Bước nhảy = 4 (bmGs[5]=bmBc[C]-8+6)

Bước 5
T


H CA T CHCAHAHAHT A T ACAHT ACH
2 1

P

HC AHAHAH
Bước nhảy = 7 (bmGs[6])

Số phép so sánh ký tự là 17.
2.2.4. Đánh giá độ phức tạp của thuật toán
Các mảng bmGs và bmBc có thể được tính toán trước trong thời gian tỉ lệ với
Θ(m+δ). Thời gian tìm kiếm (độ phức tạp tính toán) của thuật toán Boyer-Moore là
Θ(m*n). Tuy nhiên với những bảng chữ cái lớn thuật toán thực hiện rất nhanh. Trong
trường hợp tốt chi phí thuật toán có thể xuống đến Θ(n/m) là chi phí thấp nhất của các
thuật toán tìm kiếm hiện đại có thể đạt được.
Thuật toán Boyer-Moore có thể đạt tới chi phí Θ(n/m) là nhờ có cách dịch thứ 2
“ký tự không khớp”. Cách dịch chuyển 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 chi phí thuật toán của Boyer-Moore là Θ(m*n) vì cách dịch thứ nhất
của thuật toán này không phân tích triệt để các thông tin của những lần thử trước, những
đoạn đã so sánh rồi vẫn có thể bị so sánh lại. 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.

18



×