You are on page 1of 86

MỤC LỤC

Chương 1. Mở đầu .................................................................................. .. 7


1.1 Giới thiệu ... ............................................................................... 7
1.2 Khái niệm về ngôn ngữ ... ........................................................ ... 7
1.2.1 Bảng chữ ... ........................................................................... . 8
1.2.2 Xâu ... ......................................................................................... . 8
1.2.3 Các phép toán trên xâu ... ..................................................... . 8
1.2.4 Ngôn ngữ... ....................................................................... 10
1.2.5 Các phép toán trên ngôn ngữ ........................................... 11
1.3 Khái niệm về văn phạm ... ........................................................ 12
1.3.1 Định nghĩa hình thức về văn phạm ... .............................. 13
1.3.2 Phân cấp văn phạm của Chomsky ... ............................... 16
1.4 Khái niệm về ô-tô-mát ... ........................................................ 17
1.5 Tổng kết chương ... ................................................................. 19
1.6 Bài tập chương 1 ... ................................................................. 19
Chương 2. Ô-tô-mát hữu hạn ... ............................................................. 21
2.1 Ô-tô-mát hữu hạn đơn định ... .............................................. 21
2.1.1 Mô tả không hình thức ... .................................................... 21
2.1.2 Mô tả hình thức .................................................................. . 22
2.1.3 Xử lý xâu của ô-tô-mát hữu hạn đơn định ... ................... 23
2.1.4 Các cách biểu diễn đơn giản hơn của OHD ... ................. 24
2.1.5 Hàm dịch chuyển mở rộng ... ............................................. 25
2.1.6 Ngôn ngữ được thừa nhận bởi OHD ................................. 27
2.2 Ô-tô-mát hữu hạn không đơn định ...................................... 29
2.2.1 Định nghĩa hình thức ô-tô-mát hữu hạn không đơn định
29
2.2.2 Hàm dịch chuyển mở rộng ... ............................................. 31
2.2.3 Ngôn ngữ được thừa nhận bởi OHKD .............................. 32
2.3 Sự tương đương giữa OHD và OHKD ... ............................. 33
2.3.1 Xây dựng OHD từ OHKD ... ........................................... 33
2.3.2 Sự tương đương giữa OHKD và OHD ... ........................ 38

2
2.4 Ứng dụng của ô-tô-mát hữu hạn... ...................................... . 39 4.6 Bài tập chương 4 ... ................................................................. 85
2.4.1 OHKD dùng để tìm kiếm từ ... ........................................... 39
Chương 5. Văn phạm phi ngữ cảnh ... ...................................................... 88
2.4.2 OHD dùng để tìm kiếm từ... ......................................... ... 42
5.1 Văn phạm phi ngữ cảnh ........................................................ 88
2.5 Bài tập chương 2 .................................................................. .. 42 5.1.1 Định nghĩa văn phạm và ngôn ngữ phi ngữ cảnh ... ... 88
Chương 3. Biểu thức chính quy ... ...................................................... ... 46 5.1.2 Dẫn xuất trái nhất và dẫn xuất phải nhất ........................... 90
3.1 Biểu thức chính quy ... ............................................................... 46 5.2 Cây dẫn xuất ... ........................................................................... 91
3.1.1 Định nghĩa hình thức của biểu thức chính quy ... ........... . 46 5.2.1 Xây dựng cây dẫn xuất... .................................................. 91
3.1.2 Độ ưu tiên các phép toán trên biểu thức chính quy ...... 48 5.2.2 Kết quả của cây dẫn xuất ................................................. 92
3.1.3 Các tính chất đại số của biểu thức chính quy ... ............... . 48
5.3 Sự nhập nhằng trong văn phạm ........................................... 96
3.2 Biểu thức chính quy và ô-tô-mát hữu hạn ... .................... ... 51 5.3.1 Văn phạm nhập nhằng ..................................................... 96
3.2.1 Xây dựng ô-tô-mát hữu hạn từ biểu thức chính quy ..... 51 5.3.2 Loại bỏ sự nhập nhằng trong văn phạm ............................ 97
3.2.2 Xây dựng biểu thức chính quy từ ô-tô-mát hữu hạn ..... 55 5.3.3 Sự nhập nhằng cố hữu ........................................................ 99
3.3 Ứng dụng của biểu thức chính quy ... ................................ .. 59 5.4 Ứng dụng của văn phạm phi ngữ cảnh ... ...................... ... 101
3.3.1 Công cụ sinh bộ phân tích từ vựng Lex/Flex ... ............. . 59 5.4.1 Định nghĩa ngôn ngữ lập trình ... ............................... ... 102
3.3.2 Tìm kiếm xâu với lệnh grep ... ................................... ... 61 5.4.2 Công cụ sinh bộ phân tích cú pháp Yacc/Bison ... ... 103
3.4 Bài tập chương 3 .................................................................. .. 61 5.5 Dạng chuẩn của văn phạm phi ngữ cảnh ........................ ... 105
5.5.1 Loại bỏ ký hiệu vô ích ... ............................................ ... 105
Chương 4. Văn phạm chính quy và tính chất của ngôn ngữ chính
5.5.2 Loại bỏ luật sinh- ... .................................................. ... 109
quy ... ....................................................................................................................................... . 64
5.5.3 Loại bỏ luật sinh đơn vị ................................................. 112
4.1 Văn phạm chính quy ... ............................................................. 64 5.5.4 Giản lược văn phạm phi ngữ cảnh ... ......................... ... 114
4.1.1 Văn phạm tuyến tính phải và văn phạm tuyến tính trái 64 5.5.5 Dạng chuẩn Chomsky ... ................................................... 115
4.1.2 Ngôn ngữ chính quy và văn phạm chính quy ... ........... ... 65
5.6 Bài tập chương 5 ... ........................................................... ... 118
4.2 Các tính chất đóng của ngôn ngữ chính quy ... ................. .. 68
4.2.1 Tính đóng của ngôn ngữ chính quy dưới các phép toán Chương 6. Ô-tô-mát đẩy xuống ... ..................................................... .. 120
tập hợp 68 6.1 Ô-tô-mát đẩy xuống ... ............................................................. 120
4.2.2 Tính đóng dưới các phép toán khác ... .......................... ... 71 6.1.1 Mô tả không hình thức ... .............................................. ... 120
6.1.2 Định nghĩa hình thức... ............................................... ... 121
4.3 Các thuật toán liên quan đến ngôn ngữ chính quy ... ........ . 73
6.1.3 Biểu diễn ODX bằng biểu đồ ... ....................................... 123
4.4 Sự tương đương và cực tiểu hóa các ô-tô-mát ................. ... 74 6.1.4 Cấu hình của ODX ... .................................................... ... 124
4.4.1 Sự tương đương của các trạng thái ... ............................. . 74
4.4.2 Sự tương đương của các OHD ... ....................................... 77 6.2 Ngôn ngữ được đoán nhận bởi ODX ... ................................ 125
6.2.1 Đoán nhận bởi trạng thái cuối ... ...................................... 125
4.4.3 Cực tiểu hóa OHD... ..................................................... ... 78
6.2.2 Đoán nhận bởi ngăn xếp rỗng ... .................................... 127
4.5 Nhận biết các ngôn ngữ không chính quy ... .................... ... 82 6.2.3 Chuyển từ ODX đoán nhận bởi ngăn xếp rỗng thành
4.5.1 Định lý bơm cho ngôn ngữ chính quy ... ....................... .. 82 ODX đoán nhận bởi trạng thái cuối ... ............................................ ... 128
4.5.2 Ứng dụng định lý bơm ... .................................................... 84

3 4
6.2.4 Chuyển ODX đoán nhận bởi trạng thái cuối thành ODX 7.6 Bài tập chương 7 ... ........................................................... ... 169
đoán nhận bởi ngăn xếp rỗng ... .......................................................... 130
6.3 Sự tương đương giữa ODX và văn phạm phi ngữ cảnh 132
6.3.1 Chuyển văn phạm phi ngữ cảnh thành ODX ... ............. 132
6.3.2 Chuyển ODX thành văn phạm phi ngữ cảnh ... ............. 135
6.4 Ô-tô-mát đẩy xuống đơn định ............................................. 141
6.5 Ngôn ngữ chính quy và ODX đơn định ... .......................... 142
6.6 Các tính chất của ngôn ngữ phi ngữ cảnh ... ...................... 143
6.6.1 Tính đóng dưới phép hợp ... ........................................... 143
6.6.2 Tính đóng dưới phép ghép nối ....................................... 143
6.6.3 Tính đóng dưới phép bao đóng ... ................................... 144
6.6.4 Tính đóng dưới các phép toán khác ... ............................ 144
6.7 Các thuật toán liên quan đến ngôn ngữ phi ngữ cảnh ... 145
6.8 Nhận biết các ngôn ngữ không phi ngữ cảnh ... ................. 146
6.8.1 Kích thước cây dẫn xuất ... ............................................. 147
6.8.2 Định lý bơm cho ngôn ngữ phi ngữ cảnh ... ................... 147
6.8.3 Ứng dụng định lý bơm cho ngôn ngữ phi ngữ cảnh ... 150
6.9 Bài tập chương 6 ................................................................... 151
Chương 7. Máy Turing ... ...................................................................... 153
7.1 Máy Turing ... ........................................................................ 153
7.1.1 Mô tả máy Turing ... ....................................................... 153
7.1.2 Biểu diễn máy Turing bằng biểu đồ ... ........................... 157
7.1.3 Cấu hình của máy Turing ... ........................................... 157
7.1.4 Ngôn ngữ được đoán nhận bởi máy Turing ... ............... 159
7.2 Tính toán bởi máy Turing ... ................................................ 159
7.3 Luận đề Church-Turing ... ................................................... 160
7.4 Các kỹ thuật xây dựng máy Turing ... ................................ 161
7.4.1 Nhớ ở bộ điều khiển hữu hạn ... ..................................... 161
7.4.2 Băng nhiều rãnh ... .......................................................... 162
7.4.3 Chương trình con ... ........................................................ 165
7.5 Các mô hình khác của máy Turing ... ................................. 167
7.5.1 Máy Turing có nhiều băng ............................................. 167
7.5.2 Máy Turing không đơn định ... ....................................... 168

5 6
1.2.1 Bảng chữ
Bảng chữ (alphabet) là một tập hợp hữu hạn không rỗng các phần tử.
Mỗi phần tử của bảng chữ được gọi ký tự hay ký hiệu. Bảng chữ thường
được ký hiệu là .
Chương 1. Mở đầu
Ví dụ 1.1. Cho các bảng chữ sau:
{a, b, c, …, z} : bảng chữ cái Latin,
{0, 1, …, 9} : bảng chữ số thập phân,
{0, 1} : bảng chữ số nhị phân.
1.1 Giới thiệu
Vào những năm 1930, trước khi máy tính ra đời, Alain Turing đã 1.2.2 Xâu
nghiên cứu máy trừu tượng có khả năng thực hiện các tính toán như máy tính Cho bảng chữ , xâu (hay còn gọi từ, chuỗi, câu) là một dãy hữu hạn các
ngày nay. Máy trừu tượng này được gọi là máy Turing. Mục tiêu của Turing ký hiệu được chọn từ bảng chữ.
là nghiên cứu các giới hạn mà một máy tính có thể thực hiện, kết quả
nghiên cứu này không chỉ đúng với máy trừu tượng Turing, mà còn đúng Thông thường, chúng ta sử dụng các chữ cái in thường ở đầu bảng chữ cái
với cả các máy tính ngày nay. Latin a, b, c… để biểu diễn các ký hiệu thuộc bảng chữ và các chữ cái in
thường ở cuối bảng chữ cái Latin w, u, v… để biểu diễn các xâu.
Vào những năm 1940 và 1950, các máy trừu tượng đơn giản hơn, mà
chúng ta gọi là ô-tô-mát hữu hạn, đã được nghiên cứu bởi các nhà khoa Ví dụ 1.2. Cho bảng chữ  = {a, b, c} các xâu abcabc và aabbab được
học. Sau đó, vào những năm 1950, nhà ngôn ngữ học Chomsky đã thực chọn từ bảng chữ .
hiện các nghiên cứu về văn phạm hình thức. Văn phạm này có mối quan hệ Xâu rỗng là xâu không chứa ký hiệu nào, thường được ký hiệu là .
chặt chẽ với ô-tô-mát và ngày nay văn phạm là một phần nền tảng trong việc
xây dựng một số phần mềm, đặc biệt là các chương trình dịch. 1.2.3 Các phép toán trên xâu
Các cơ sở lý thuyết này đóng vai trò rất quan trọng trong lĩnh vực khoa Độ dài xâu
học máy tính ngày nay. Các khái niệm như ô-tô-mát và ngôn ngữ hình Độ dài của một xâu là số ký hiệu của xâu. Độ dài của xâu w được ký
thức được sử dụng để thiết kế và phát triển một số lớn các loại phần mềm. hiệu là |w|.
Trong chương này, chúng ta sẽ bắt đầu làm quen với các khái niệm cơ Ví dụ 1.3. |0110| = 4 và || = 0.
bản, gồm: ngôn ngữ, văn phạm và ô-tô-mát.
Ví dụ 1.4. Có bao nhiêu xâu tạo nên từ bảng chữ {a1, a2, …, ak} có độ dài
1.2 Khái niệm về ngôn ngữ n, với n là số nguyên dương ?

Một ngôn ngữ, cho dù là ngôn ngữ tự nhiên hay ngôn ngữ lập trình, thì đều Có tất cả n vị trí trong chuỗi có độ dài n, mỗi vị trí có thể nhận một trong k
được xem là một tập hợp các câu hay các xâu ký hiệu. Tuy nhiên, trước ký hiệu từ bảng chữ. Như vậy, có tất cả nk xâu có độ dài n.
khi có định nghĩa chính xác về ngôn ngữ, chúng ta sẽ tìm hiểu một số các Nối xâu
khái niệm hình thức về ngôn ngữ. Cho hai xâu u và v. Ký hiệu uv là phép nối hai xâu u và v. Xâu uv được tạo
nên bằng cách nối các ký hiệu của xâu v vào cuối cùng bên phải của xâu u.
Một cách chính xác hơn, giả sử u = a1a2 … an và v = b1b2 … bm thì xâu uv có
độ dài là n + m và uv = a1a2 … anb1b2 … bm.
8

7
Ví dụ 1.5. Cho xâu u = 010 và xâu v = 111. Xâu uv = 010111 và xâu Tập tất cả các xâu trên bảng chữ , được ký hiệu là *. Vậy chúng ta có
vu = 111010. thể biểu diễn:
Lưu ý, cho xâu w bất kỳ, thì w = w = w. * = 0  1  2  3 …
Đảo xâu Ví dụ 1.9. Cho  = {0, 1}. Thì * = {, 0, 1, 00, 01, 10, 11, 000, …}.
Đảo một xâu là viết các ký hiệu của xâu theo thứ tự ngược lại. Cho xâu w = Đôi khi, chúng ta muốn loại bỏ ký hiệu rỗng khỏi tập tất cả các xâu. Tập
a1a2 … an, thì đảo xâu w, được ký hiệu là wR, wR = anan-1 … a1. tất cả các xâu không chứa xâu rỗng từ  được ký hiệu là +. Như vậy:
Lưu ý, đảo xâu rỗng cho kết quả là xâu rỗng, R = . + = 1  2  3 …
Ví dụ 1.6. Cho các chuỗi u và v, chứng minh rằng (uv)R = vRuR. Nếu u = , thì Nghĩa là: + = * - {}
uR = , như thế (uv)R = vR = uRvR. Nếu v = , thì vR = , như thế
(uv)R = uR = uRvR. Giả sử u = a1a2 … am và v = b1b2 … bn với m,n ≥ 1. 1.2.4 Ngôn ngữ
(uv)R = (a1a2 … amb1b2 … bn)R = b1b2 … bna1a2 … am = vRuR.
Tập hợp các xâu được chọn từ *, với  là một bảng chữ, được gọi là
Tiền tố và hậu tố ngôn ngữ. Ngôn ngữ thường được ký hiệu là L. Các khái niệm ngôn ngữ mà
Cho xâu w. Nếu w = uv thì u được gọi là tiền tố của w và v được gọi là hậu chúng ta thường gặp cũng được xem là tập các xâu. Chẳng hạn, tiếng Việt là
tố của w. tập hợp tất cả các từ có nghĩa được tạo ra bởi bảng chữ cái tiếng Việt. Ngôn
ngữ lập trình C gồm các chương trình, mà mỗi chương trình là tập hợp các
Ví dụ 1.7. Cho xâu w = abc. Tiền tố của w gồm các xâu: , a, ab, abc. Hậu tố xâu được tạo nên từ bảng chữ cái của ngôn ngữ C. Bảng chữ cái này gồm
của w gồm các xâu: , c, bc, abc. các ký tự in thường, ký tự in hoa, các chữ số, các dấu ngăn cách và các ký
Lũy thừa xâu hiệu toán học.
Cho xâu w. Lũy thừa xâu w, được ký hiệu là wn, là xâu nhận được bằng Chúng ta ký hiệu  là ngôn ngữ rỗng, tức là không chứa bất kỳ ký hiệu
cách kết nối w với chính nó n lần. Nghĩa là: nào.
wn = ww … w. {} là ngôn ngữ chỉ chứa xâu rỗng . Lưu ý, ngôn ngữ rỗng  khác với
n lần ngôn ngữ chỉ chứa xâu rỗng {}. Ngôn ngữ rỗng không chứa bất cứ xâu nào,
kể cả xâu rỗng. Trong khi ngôn ngữ {} chỉ chứa xâu rỗng .
Lưu ý, w0 =  với mọi w.
Ví dụ 1.10. Cho  = {0, 1}
Lũy thừa bảng chữ
1. Ngôn ngữ gồm các xâu bắt đầu bởi ký hiệu 0 và kết thúc bởi ký
Nếu  là một bảng chữ, chúng ta có thể biểu diễn tất cả các xâu tạo nên từ
hiệu 1: {01, 001, 0101, 01101, …}.
 bởi phép lũy thừa. Chúng ta định nghĩa, k là tập hợp các xâu có độ dài k
được tạo nên từ . 2. Ngôn ngữ gồm các xâu có độ dài chẵn trên : {00, 01, 10, 11,
0000, 0001, 0011, 1111, …}.
Lưu ý, 0 = {} với mọi bảng chữ .
3. L = {(010)n | n > 0} là một ngôn ngữ gồm các xâu {010,
Ví dụ 1.8. Cho  = {0, 1}. Vậy 1 = {0, 1}, 2 = {00, 01, 10, 11},…
010010, 010010010, …} trên .
Lưu ý, cần phân biệt  và 1.  chứa các ký hiệu 0 và 1. Trong khi, 1
Lưu ý, các bảng chữ luôn chứa hữu hạn các ký hiệu. Tuy nhiên, các
chứa các xâu ký hiệu 0 và 1.
ngôn ngữ có thể chứa vô hạn các xâu được tạo nên từ một bảng chữ hữu

9 10
hạn. Ngôn ngữ chứa số xâu hữu hạn được gọi là ngôn ngữ hữu hạn. Ví dụ 1.15. Cho L = {10, 100, 1100, 110000}. Khi đó, LR = {01, 001,
Ngược lại, ngôn ngữ chứa vô số xâu được gọi là ngôn ngữ vô hạn. 0011, 000011}.
Ví dụ 1.11. Phép lũy thừa
L1 = {a, ab, abb, bba, bbb} là ngôn ngữ hữu hạn trên {a, b}. Ln = LL…L (n lần)

L2 = {(ab)n | n > 0} là ngôn ngữ vô hạn trên {a, b}. Hay L0 = {}, Li = LLi-1
Phép bao đóng (closure)
1.2.5 Các phép toán trên ngôn ngữ
L* = L0  L1  L2  …
Ngôn ngữ là một tập hợp, do đó tất cả các phép toán trên tập hợp đều có
Phép bao đóng dương
thể áp dụng cho ngôn ngữ. Ngoài ra ngôn ngữ còn có một số phép toán quan
trọng khác. L+ = L1  L2  L3  …
Cho các ngôn ngữ L, L1 và L2 trên bảng chữ . Lưu ý: L* = L+  {}
Phép hợp L+ = LL* = L*L
L1  L2 = {w | w  L1 hoặc w  L2} Ví dụ 1.16. Cho L = {a, b}, khi đó
Phép giao L2 = {aa, ab, bb, ba},
L1  L2 = {w | w  L1 và w  L2} L4 = {aaaa, aaab, aabb, aaba, abaa, abab, abbb, abba, bbaa,
Phép hiệu bbab, bbbb, bbba, baaa, baab, babb, baba}.
L1 - L2 = {w | w  L1 và w  L2} Ví dụ 1.17. Hãy chỉ ra rằng L+ = L* khi và chỉ khi   L. Ta có L+
Phép bù = L1  L2  L3  …, mà   L nên   L+. Trong khi, L* = L+  {}. Vậy L*
= L+.
L = {w | w  L} hoặc L = * - L
Ví dụ 1.18. Cho ngôn L1 và L2, hãy chỉ ra rằng (L1L2)R = L2RL1R. Thật vậy:
Ví dụ 1.12. Cho L = {00, 01, 10, 11}. Khi đó ngôn ngữ bù của L gồm mọi xâu
trên bảng chữ , ngoại trừ các xâu 00, 01, 10 và 11. (L1L2)R = {wR | w  L1L2}
Phép nối = {(uv)R | u  L1, v  L2}
L1L2 = {w | w = uv, u  L1 và v  L2}. = {vRuR | u  L1, v  L2}, theo ví dụ 1.6
Ví dụ 1.13. Cho L1 = {0, 1} và L2 = {00, 11} = {vR| v  L2}.{uR | u  L1}
L1L2 = {000, 011, 100, 111}. = L2RL1R
Ví dụ 1.14. Cho L1 = {(01)n | n ≥ 0} và L2 = {01, 010}. Khi đó, 1.3 Khái niệm về văn phạm
L1L2 = {(01)n, (01)n0 | n ≥ 1}. Khi nghiên cứu ngôn ngữ cần một cơ chế mô tả ngôn ngữ đó chính là văn
Phép nghịch đảo phạm (grammar). Một cách không hình thức, văn phạm là các quy tắc tạo ra
LR = {w | wR  L} câu đúng.
Đối với ngôn ngữ tự nhiên, văn phạm là hệ thống ngữ pháp. Đối với
ngôn ngữ lập trình, văn phạm là các quy tắc cú pháp viết chương trình.
11 12
Ví dụ 1.19. Định nghĩa một câu tiếng Việt đơn giản bởi văn phạm sau: 3. Một biến trong tập hợp các biến, được gọi là biến đầu. Các biến
khác biểu diễn các lớp bổ sung các xâu được sử dụng để định
<Câu> → <Chủ ngữ> <Vị ngữ> nghĩa ngôn ngữ được biểu diễn bởi biến đầu.
<Chủ ngữ> → <Danh từ> | <Danh từ> <Tính từ>
4. Một tập hợp hữu hạn các luật sinh hay sản xuất biểu diễn định
<Vị ngữ> → <Động từ> | <Động từ> <Bổ ngữ> nghĩa đệ quy của một ngôn ngữ. Mỗi luật sinh bao gồm:
<Bổ ngữ> → <Trạng từ> | <Danh từ> <Tính từ> a. Phần đầu của luật sinh, gồm một dãy các ký hiệu kết thúc,
Văn phạm trên sinh ra các câu đúng sau: các biến và phải chứa ít nhất một biến.
- Học sinh học giỏi. b. Ký hiệu sản xuất →.
- Con hổ ăn con bò đen. c. Phần thân của luật sinh, gồm một dãy các ký hiệu kết thúc
và các biến.
Chúng ta có thể biểu diễn quá trình sản sinh câu “Học sinh học giỏi”
bởi cấu trúc dạng cây như trong hình vẽ 1.1. Bây giờ, chúng ta xem xét định nghĩa hình thức văn phạm.
<Câu> Định nghĩa 1.1. Văn phạm G được định nghĩa là bộ bốn:

<Chủ ngữ> <Vị ngữ> G = (N, , R, S)


trong đó:
<Danh từ> <Động từ> <Bổ ngữ>
- N là tập hợp hữu hạn các ký hiệu không kết thúc hay các biến;
<Trạng từ>
Học sinh học -  là bảng chữ, tập các ký hiệu kết thúc, N   = ;
- S  N là ký hiệu đầu hay biến đầu;
giỏi
- R là tập các luật sinh hay các sản xuất có dạng:
Hình 1.1. Cây biểu diễn sản sinh câu.
→
1.3.1 Định nghĩa hình thức về văn phạm trong đó   (N  )+ có chứa ít nhất một biến và   (N  )*.
Một cách không hình thức, mô tả một văn phạm gồm bốn thành phần cơ Một số quy ước
bản: - Các biến hay ký hiệu không kết thúc thuộc N được biểu diễn bởi
1. Một tập hợp hữu hạn các ký hiệu được sử dụng để tạo nên các xâu các ký tự in hoa ở đầu bảng chữ cái: A, B, C, …
của ngôn ngữ. Chẳng hạn, trong các ví dụ trên tập hợp này là - Các ký hiệu kết thúc thuộc  được biểu diễn bởi các ký tự in
bảng chữ {0, 1}. Chúng ta gọi bảng chữ này là các ký hiệu kết thường ở đầu bảng chữ cái: a, b, c, …
thúc.
- Các xâu chỉ gồm các ký hiệu kết thúc được biểu diễn bởi các ký
2. Một tập hợp hữu hạn các biến, còn được gọi là các ký hiệu không tự in thường ở cuối bảng chữ cái: w, u, v, …
kết thúc. Mỗi biến biểu diễn một ngôn ngữ, nghĩa là một tập hợp
các xâu. - Các xâu gồm các ký hiệu kết thúc và các biến được biểu diễn
bởi các ký tự: , , , …
Ví dụ 1.20. Cho văn phạm G1 = ({S}, {0, 1}, {S → 0S1 | }, S).

13 14
Ví dụ 1.21. Cho văn phạm G2 = ({S, A, B}, {a, b}, R, S), trong đó R gồm nghĩa sản sinh xâu từ một văn phạm, chúng ta định nghĩa ngôn ngữ được
các luật sinh sau: sản sinh bởi một văn phạm.
S → aS | bA Định nghĩa 1.4. Cho văn phạm G = (N, , R, S), ngôn ngữ L do văn
phạm G sinh ra, được ký hiệu L(G), được định nghĩa là:
A → bbB
*
B → bB | aA |  L(G) = {w  * | S ⇒ w }
G
Để sản sinh ra xâu từ văn phạm, chúng ta có khái niệm dẫn xuất.
Nghĩa là, ngôn ngữ được sinh ra bởi văn phạm G gồm mọi xâu được sản
Định nghĩa 1.2. Cho văn phạm G = (N, , R, S) và hai xâu sinh ra bởi văn phạm đó.
u  (N  )+ và v  (N  )*
Ví dụ 1.22. Cho văn phạm G = ({S}, {0, 1}, R, S), trong đó R gồm các luật
- Dẫn xuất trực tiếp (hay còn gọi là dẫn xuất một bước): ta nói u sinh:
dẫn xuất trực tiếp ra v, ký hiệu u ⇒ v , khi và chỉ khi:
G S → 0S1 | 
u = xy Khi đó, S ⇒ 0S1 ⇒ 00S11 ⇒ 000S111 ⇒ 000111 là một dẫn xuất sinh ra
xâu 000111 bởi văn phạm G.
v = xy
Chúng ta dễ dàng nhận thấy, ngôn ngữ sinh ra bởi văn phạm G gồm các xâu
→R
có dạng: L(G) = {0n1n | n  0}.
- Dẫn xuất gián tiếp (hay còn gọi là dẫn xuất nhiều bước): ta nói
*
Ví dụ 1.23. Cho văn phạm G = ({S, A}, {a, b}, R, S) , trong đó R gồm các luật
u dẫn xuất gián tiếp ra v, ký hiệu u ⇒ v , khi và chỉ khi: sinh:
G
S → aA
u ⇒ w 1⇒ w 2 ⇒ ⇒v
G G G G
A → aA
Từ định nghĩa dẫn xuất, chúng ta định nghĩa sản sinh xâu bởi một văn A→b
phạm.
Định nghĩa 1.3. Cho văn phạm G = (N, , R, S), câu w  * do văn Ngôn ngữ sinh ra bởi văn phạm G là: L(G) = {anb | n > 0}.
phạm G sinh ra khi và chỉ khi:
1.3.2 Phân cấp văn phạm của Chomsky
*
S⇒w Theo nhà ngôn ngữ học Chomsky, có bốn loại văn phạm theo các dạng của
G
luật sinh như sau:
Nghĩa là, phải tồn tại: S ⇒ 1 ⇒  2 ⇒ ⇒ w , các xâu 1, 2, …được 1. Nếu các luật sinh đều có dạng A → a hoặc A → aB với
G G G G
gọi là các dạng xâu của dẫn xuất. A, B  N, a   thì văn phạm được gọi là văn phạm chính quy
(regular grammars). Ngôn ngữ được sản sinh vởi văn phạm
Như vậy, quá trình sản sinh một xâu bởi văn phạm luôn bắt đầu bởi chính quy được gọi là ngôn ngữ chính quy.
biến đầu S. Quá trình dẫn xuất sẽ dừng lại khi dạng xâu chỉ chứa các ký
hiệu kết thúc. 2. Nếu các luật sinh có dạng A → , A  N,   (N  )* thì văn
phạm được gọi là văn phạm phi ngữ cảnh (context-free
Chúng ta đã biết, ngôn ngữ được sinh ra bởi một văn phạm gồm tập grammars). Ngôn ngữ được sản sinh vởi văn phạm phi ngữ cảnh
hợp tất cả các xâu được sinh ra bởi một văn phạm đó. Từ đó, dựa trên định được gọi là ngôn ngữ phi ngữ cảnh.
15 16
3. Nếu các luật sinh có dạng  → ,   (N  )+,   (N  )*
thỏa mãn ||  || thì văn phạm được gọi là văn phạm cảm ngữ
ấn nút
cảnh (context-sensitive grammars). Ngôn ngữ được sản sinh vởi
văn phạm cảm ngữ cảnh được gọi là ngôn ngữ cảm ngữ cảnh.
4. Nếu không có hạn chế gì trên các luật sinh thì văn phạm được Bật
gọi là văn phạm tự do (unrestricted grammars). Ngôn ngữ được Tắt
sản sinh vởi văn phạm tự do được gọi là ngôn ngữ liệt kê đệ quy
(recursively enumerable languages).
ấn nút
Lưu ý rằng, văn phạm chính quy là tập con của văn phạm phi ngữ cảnh,
văn phạm phi ngữ cảnh là tập con của văn phạm cảm ngữ cảnh, và văn Hình 1.2. Mô hình ô-tô-mát hữu hạn mô tả thiết bị chuyển mạch
phạm cảm ngữ cảnh là tập con của văn phạm tự do. Ô-tô-mát trên mô tả hai trạng thái bật và tắt của thiết bị, khi có sự tác
động từ bên ngoài “ấn nút” thì nó sẽ chuyển từ trạng thái này sang trạng
1.4 Khái niệm về ô-tô-mát thái khác.
Có rất nhiều hệ thống có thể được xem tại mỗi thời điểm thì ở trong một Một trong số các trạng thái được đánh dấu là trạng thái đầu, nghĩa là
trạng thái nhất định của một tập hợp hữu hạn các trạng thái. Mục đích của trạng thái mà hệ thống bắt đầu hoạt động. Trong ví dụ trên, trạng thái đầu là
trạng thái là ghi nhớ lại một phần lịch sử của hệ thống. Thuận lợi của việc chỉ tắt. Chúng ta thường ký hiệu trạng thái đầu bởi một mũi tên chỉ vào trạng
có số hữu hạn các trạng thái là một hệ thống có thể được cài đặt bởi tập hợp thái đó.
hữu hạn tài nguyên.
Ngoài ra, một hoặc nhiều trạng thái được coi là trạng thái cuối hay
Một cách không hình thức, một ô-tô-mát gồm một tập hợp các trạng trạng thái chấp nhận. Khi đạt đến một trong các trạng thái này, sau một dãy
thái và các điều khiển dịch chuyển từ trạng thái này sang trạng thái khác khi các dữ liệu vào, có thể xem dãy các dữ liệu là tốt. Chẳng hạn trong ví dụ trên,
nhận dữ liệu vào. Như thế, với các hệ thống được đề cập ở trên, chúng ta có chúng ta có thể xem bật là trạng thái cuối, bởi vì khi ở trạng thái này thiết bị
thể biểu diễn chúng bởi các ô-tô-mát. đang được điều khiển bởi chuyển mạch sẽ hoạt động. Thông thường, các
Ví dụ 1.24. Một ô-tô-mát đơn giản mô tả các trạng thái của một chuyển trạng thái cuối được biểu diễn bởi hình tròn hai vòng.
mạch. Thiết bị cần ghi nhớ trạng thái của nó là bật hay tắt, cho phép người Ví dụ 1.25. Ô-tô-mát mô tả một phần của bộ phân tích từ vựng. Hình 1.3 mô
sử dụng ấn nút thì hiệu ứng nó phụ thuộc vào trạng thái hiện tại của thiết tả ô-tô-mát hữu hạn nhận biết từ khóa begin.
bị. Khi thiết bị ở trạng thái bật, người sử dụng ấn nút thì nó sẽ chuyển
sang trạng thái tắt, ngược lại khi thiết bị đang ở trong trạng thái tắt người
sử dụng ấn nút thì nó chuyển sang trạng thái bật. Mô hình ô-tô-mát hữu b e g i n
hạn cho một chuyển mạch của thiết bị được mô tả trong hình 1.2. b be beg begi begin

Hình 1.3 Mô hình ôtônát hữu hạn đoán nhận từ khóa begin
Mỗi trạng thái của ô-tô-mát biểu diễn phần xâu đã được nhận biết của từ
khóa begin. Quá trình nhận biết bắt đầu từ xâu rỗng, cho đến khi xâu begin
được nhìn thấy thì trạng thái cuối cho phép đoán nhận từ khóa.

17 18
Ô-tô-mát là mô hình hữu ích cho nhiều loại phần mềm và phần cứng S→
quan trọng. Trong các chương tiếp theo, chúng ta sẽ trình bày các định
a. Hãy xây dựng dẫn xuất sinh ra các xâu ababaab, bbabbba và
nghĩa và ví dụ về các loại ô-tô-mát. Dưới đây, chúng ta liệt kê ra một vài ứng
bbaabba.
dụng điển hình của ô-tô-mát:
b. Hãy mô tả ngôn ngữ được sản sinh bởi G.
- Phần mềm thiết kế và kiểm tra các mạch điện tử số.
Bài 1.6. Cho văn phạm G = ({S, A}, {a, b}, R, S) , trong đó R gồm các luật
- Bộ phân tích từ vựng của một chương trình dịch, tức là một sinh:
thành phần cơ bản của trình biên dịch cho phép nhận biết cú
pháp của một chương trình. S → abA
- Dịch từ ngôn ngữ tự nhiên này sang ngôn ngữ tự nhiên khác A → bbA
(Anh, Pháp, Việt, …). A → aaA
- Phần mềm cho phép tìm kiếm sự xuất hiện của từ, câu hay các A → ba
mẫu trong văn bản.
Hãy mô tả ngôn ngữ được sản sinh bởi G.
1.5 Tổng kết chương
Chương này đã trình bày các khái niệm cơ bản như bảng chữ, xâu và
ngôn ngữ. Chúng ta cũng đã được làm quen với các khái niệm hình thức về
văn phạm, sản sinh câu và sản sinh ngôn ngữ. Khái niệm ô-tô-mát được trình
một cách không hình thức qua các ví dụ đơn giản. Trong chương tiếp theo,
chúng ta sẽ tìm hiểu đầy đủ về ô-tô-mát hữu hạn.

1.6 Bài tập chương 1


Bài 1.1. Cho L1 = {abc, } và L2 = {bc, abc}, hãy xác định các ngôn ngữ
L1L2 và L1*L2.
Bài 1.2. Cho các ngôn ngữ L1 = {a(bc)n | n ≥ 0} và L2 = {a, bca}, hãy xác
định các ngôn ngữ L1L2 và L1(L2)m với m > 0.
Bài 1.3. Hãy chỉ ra rằng ngôn ngữ {0, 10}* gồm tập hợp các xâu nhị
phân không chứa xâu con 11 và kết thúc bởi 0.
Bài 1.4. Cho các ngôn ngữ L1 và L2, hãy chỉ rằng
(L1  L2)R = L1R  L2R.
Bài 1.5. Cho văn phạm G = ({S }, {a, b}, R, S) , trong đó R gồm các luật
sinh:
S → aS
S → bS

19 20
0 0 1 1 0 1 0 1 1 1 0
Chương 2. Ô-tô-mát hữu hạn Băng vào
Đầu đọc

Chương này sẽ giới thiệu lớp ngôn ngữ chính quy. Lớp ngôn ngữ này
được mô tả bởi ô-tô-mát hữu hạn. Như chúng ta đã trình bày ở chương Bộ điều khiển q
trước, ô-tô-mát hữu hạn gồm một tập hợp các trạng thái và các điều khiển
dịch chuyển từ trạng thái này sang trạng thái khác khi nhận dữ liệu vào. Hình 2.1. Mô tả ô-tô-mát hữu hạn đơn định
Lớp ô-tô-mát hữu hạn được chia làm hai loại: ô-tô-mát hữu hạn đơn định Hoạt động của ô-tô-mát được thực hiện theo từng bước. Mỗi bước như
và ô-tô-mát hữu hạn không đơn định. Ô-tô-mát hữu hạn đơn định là ô-tô- sau: tùy theo trạng thái hiện thời của bộ điều khiển và ký hiệu mà đầu đọc
mát mà tại một thời điểm nó chỉ có thể ở trong một trạng thái nhất định, đang đọc, ô-tô-mát chuyển sang một trạng thái mới, đồng thời đầu đọc
trong khi ô-tô-mát hữu hạn không đơn định (hay ô-tô-mát hữu hạn bất dịch chuyển sang phải một ô.
định) là ô-tô-mát mà tại mỗi thời điểm có thể ở trong nhiều trạng thái khác
Quy luật chuyển trạng thái của ô-tô-mát hữu hạn đơn định được mô tả
nhau.
bởi một hàm, được gọi là hàm dịch chuyển (transition function) như sau:
2.1 Ô-tô-mát hữu hạn đơn định :Qx→Q

2.1.1 Mô tả không hình thức Trong tập hữu hạn các trạng thái Q, có một trạng thái đầu, thường
được ký hiệu q0 và một tập hợp các trạng thái cuối hay trạng thái thừa
Ô-tô-mát hữu hạn đơn định (deterministic finite automata) là một cái nhận, thường được ký hiệu F (F  Q).
“máy” cho phép đoán nhận xâu. Nó bao gồm các thành phần sau:
Ta nói ô-tô-mát thừa nhận xâu vào w nếu sau khi xuất phát từ trạng thái
- một băng vào được chia thành ô, dùng để ghi xâu vào, mỗi ký đầu q0 và đầu đọc chỉ vào ký hiệu bên trái nhất của xâu w, sau một số
hiệu của xâu vào thuộc bảng chữ  được ghi trên một ô; bước dịch chuyển hữu hạn, ô-tô-mát đọc xong xâu w và ở vào một trong các
- một đầu đọc, mỗi thời điểm đọc một ô trên băng vào; trạng thái cuối thuộc F.
- một bộ điều khiển Q, gồm một số hữu hạn các trạng thái, tại mỗi Tập hợp tất cả các xâu đoán nhận bởi ô-tô-mát hợp thành ngôn ngữ
thời điểm nó có một trạng thái xác định q  Q. được thừa nhận bởi ô-tô-mát đó.
Hình 2.1 minh họa các thành phần của một ô-tô-mát hữn hạn. 2.1.2 Mô tả hình thức
Định nghĩa 2.1. Một ô-tô-mát hữu hạn đơn định được định nghĩa là
một bộ năm
M = (Q, , , q0, F),
trong đó:
- Q là tập hữu hạn các trạng thái, Q = {q0, q1, …, qn};
-  là bảng chữ vào;

21 22
-  : Q x  → Q là hàm dịch chuyển,  có thể được viết dưới OHD có thể tiếp tục đọc bất kỳ ký hiệu nào cho đến hết xâu vào và thừa
dạng (q, a) = q’, nghĩa là ô-tô-mát đang ở trạng thái q và nhận xâu. Như thế, (q2, 0) = (q2, 1) = q2.
đọc ký hiệu a thì nó sẽ chuyển sang trạng thái q’; Trường hợp (2) sẽ tương ứng với trạng thái đầu q0, khi ở trạng thái này
- q0  Q là trạng thái đầu; OHD có thể tiếp tục đọc các ký hiệu 1 cho đến khi gặp ký hiệu 0 thì
chuyển sang trạng thái khác. Như thế, (q0, 1) = q0, (q0, 0) = q1.
- F  Q là tập các trạng thái cuối hay trạng thái thừa nhận.
Trường hợp (3) sẽ tương ứng với trạng thái q1, khi đã đọc trước đó ít
Để đơn giản, chúng ta viết ngắn gọn một ô-tô-mát hữu hạn đơn định là
nhất một ký hiệu 0, nhưng chưa bao giờ đọc xâu 01. Ở trạng thái q1 thì
OHD.
OHD có thể tiếp tục đọc ký hiệu 0 cho đến khi gặp ký hiệu 1, thì chuyển sang
2.1.3 Xử lý xâu của ô-tô-mát hữu hạn đơn định trạng thái thừa nhận q2. Như thế, (q1, 0) = q1, (q1, 1) = q2.

Giả sử w = a0a1...an là xâu vào. OHD sẽ bắt đầu với trạng thái q0, nó sẽ Vậy, cuối cùng chúng ta có OHD như sau
thực hiện dịch chuyển (q0, a1), giả sử cho kết quả là trạng thái q1. OHD M = ({q0, q1, q2}, {0, 1}, , q0, {q2}),
bây giờ ở trạng thái q1 và ký hiệu tiếp theo sẽ đọc là a2, nó thực hiện dịch
chuyển (q1, a2) giả sử cho cho kết quả là trạng thái q2. Nó cứ tiếp tục như trong đó :
thế, cho đến khi đọc an thì sẽ chuyển sang trạng thái qn nào đó, nếu qn (q0, 0) = q1, (q0, 1) = q0,
thuộc tập các trạng thái cuối F thì OHD thừa nhận xâu vào w, ngược lại thì xâu
(q1, 0) = q1, (q1, 1) = q2,
vào sẽ không được thừa nhận.
(q2, 0) = q2, (q2, 1) = q2.
Ví dụ 2.1. Xây dựng OHD thừa nhận các xâu gồm chỉ các ký hiệu 0, 1 và
chứa ít nhất một lần xâu 01, nghĩa là chúng ta có thể mô tả ngôn ngữ L này 2.1.4 Các cách biểu diễn đơn giản hơn của OHD
như sau:
Cách mô tả OHD hình thức bởi bộ năm như trên là tương đối khó hiểu
L = {x01y | x và y gồm các ký hiệu 0 và 1 bất kỳ} và ít trực quan. Tuy nhiên, có hai cách mô tả đơn giản hơn một OHD là:
Để xây dựng OHD thừa nhận L, OHD M cần ghi nhớ các khả năng sau: biểu đồ dịch chuyển (transition diagram) và bảng dịch chuyển (transition
table).
1. OHD đã đọc xâu 01, như thế sau đó nó có thể thừa nhận xâu vào.
Biểu đồ dịch chuyển
2. OHD chưa bao giờ đọc ký hiệu 0, nhưng nó đã đọc ít nhất một ký
hiệu 1, trong trường hợp này nó có thể tiếp tục đọc các ký hiệu 1 Một biểu đồ dịch chuyển biểu diễn một OHD M = (Q, , , q0, F) là một
cho đến khi nào đọc một ký hiệu 0 đầu tiên, thì sau đó nó có thể đồ thị được định nghĩa như sau:
đọc một ký hiệu 1 đi liền sau. 1. Mỗi trạng thái trong Q là một đỉnh.
3. OHD chưa đọc xâu 01, nhưng ngay trước đó nó đọc ít nhất một 2. Với mỗi trạng thái q  Q và mỗi ký hiệu a  , có
ký hiệu 0, như thế nó có thể tiếp tục đọc ký hiệu 0 cho đến khi (q, a) = p  Q. Như thế, biểu đồ dịch chuyển có một cung đi từ
gặp một ký hiệu 1 thì có thể chuyển sang thừa nhận xâu vào nếu đỉnh q đến đỉnh p mang nhãn a, nếu có nhiều ký hiệu tạo ra dịch
hết xâu. chuyển từ q đến p thì chỉ cần biểu diễn một cung mang nhãn là
Với nhận xét trên, chúng ta dễ dàng nhận thấy mỗi trường hợp trên sẽ danh sách các ký hiệu đó.
ứng với một trạng thái ghi nhớ của OHD. Trường hợp (1) sẽ tương ứng 3. Có một mũi tên đi vào đỉnh q0 để ký hiệu trạng thái đầu.
với trạng thái thừa nhận xâu vào, ký hiệu trạng thái là q2, ở trạng thái này,
4. Các trạng thái kết thúc F là các đỉnh được biểu diễn bởi hai vòng
tròn.
23 24
5. Các trạng thái không thuộc F là các đỉnh được biểu diễn bởi chỉ 1. *(q, ) = q, với mọi trạng thái q, nếu OHD không đọc ký hiệu
một vòng tròn. vào nào thì sẽ ở lại trạng thái đó.
Ví dụ 2.2. Dùng biểu đồ dịch chuyển trạng thái để biểu diễn OHD được 2. *(q, w) = (*(q, x), a), với w = xa, x  * và a  .
xây dựng trong ví dụ 2.1. Ví dụ 2.4. Xây dựng OHD thừa nhận ngôn ngữ:
1 0 L = {w | w chỉ chứa các ký hiệu 0, 1 và luôn kết thúc bởi ký hiệu 1}.
0, 1
0 1
q0 q1 q2 OHD cần xây dựng phải phân biệt được hai khả năng:
3. Khi nó đọc ký hiệu 1, thì ngay sau đó có thể kết thúc;
Hình 2.2. OHD biểu diễn ngôn ngữ trong ví dụ 2.1 4. Khi nó đọc ký hiệu 0, thì ngay sau đó không được kết thúc, mà
Bảng dịch chuyển phải đọc tiếp các ký hiệu khác cho đến khi gặp ký hiệu 1.
Bảng dịch chuyển cho một OHD là một quy ước biểu diễn dạng bảng của Như thế, OHD sẽ có ít nhất hai trạng thái tương ứng với hai khả năng
một hàm với hai tham số - các trạng thái và các ký hiệu vào - trả về giá trị trên. Ta xây dựng OHD như sau
là một trạng thái. Các hàng của bảng tương ứng với các trạng thái, các cột
M = ({q0, q1}, {0, 1}, , q0, {q1}),
tương ứng với các ký hiệu vào.
trong đó, hàm dịch chuyển  được định nghĩa:
Trạng thái đầu được đánh dấu bởi ký hiệu ‘→’, các trạng thái cuối sẽ
được đánh dấu bởi các ký hiệu ‘*’. (q0, 0) =q0,
Ví dụ 2.3. Bảng dịch chuyển của OHD xây dựng trong ví dụ 2.1 là như (q0, 1) =q1,
sau: (q1, 0) =q0,
 0 1
→ q0 q1 q0 (q1, 1) =q1.
q1 q1 q2 OHD trên có thể được biểu diễn dạng biểu đồ như trong hình 2.3.
*q2 q2 q2

2.1.5 Hàm dịch chuyển mở rộng 0 1 1


Một cách không hình thức chúng ta có thể nhận thấy rằng, một OHD
định nghĩa ngôn ngữ gồm các xâu là kết quả của quá trình dịch chuyển từ q0 q1
trạng thái đầu đến một trong các trạng thái thừa nhận. Để xác định ngôn
ngữ được thừa nhận bởi một OHD, chúng ta sẽ định nghĩa hàm dịch 0
chuyển mở rộng (extended transition function).
Hàm dịch chuyển mở rộng, được ký hiệu là *, nhận hai tham số là Hình 2.3. OHD cho ví dụ 2.4
trạng thái q, xâu vào w và trả về trạng thái p. Nghĩa là, OHD đang ở trạng thái
q, sau khi xử lý xâu vào w thì OHD đạt đến trạng thái p. Chúng ta cũng có thể biểu diễn OHD dạng bảng dịch chuyển như sau:
 0 1
Định nghĩa 2.2. Hàm dịch chuyển mở rộng được định nghĩa đệ quy trên → q0 q0 q1
độ dài của xâu w như sau: * q1 q0 q1

25 26
Bây giờ, chúng ta sử dụng hàm dịch chuyển mở rộng để đoán nhận xâu Ví dụ 2.5. Xây dựng ô-tô-mát hữu hạn đơn định thừa nhận ngôn ngữ L
w = 101101 của ngôn ngữ L. gồm các xâu trên bảng chữ  = {a, b} luôn bắt đầu bởi xâu aa.
*(q0, ) = q0 Chúng ta có thể xây dựng OHD đoán nhận ngôn ngữ L như trong
hình 2.4.
*(q0, 1) = (*(q0, ), 1) = (q0, 1) = q1
*(q0, 10) = (*(q0, 1), 0) = (q1, 0) = q0
a, b
*(q0, 101) = (*(q0, 10), 1) = (q0, 1) = q1 a a
*(q0, 1011) = ( (q0, 101), 1) = (q1, 1) = q1
* q0 q2 q3

*(q0, 10110) = (*(q0, 1011), 0) = (q1, 0) = q0


b b
*(q0, 101101) = (*(q0, 10110), 1) = (q0, 1) = q1
Do q1 là trạng thái cuối, nên xâu vào w = 101101 được thừa nhận bởi q1 a, b
OHD.
Chúng ta có thể biểu diễn quá trình đoán nhận một cách đơn giản hơn như Hình 2.4. OHD cho ví dụ 2.5
sau:
Chúng ta dễ dàng nhận thấy rằng q1 là một trạng thái đặc biệt, nếu ô-tô-
q0101101 ⇒ q101101 ⇒ q01101 ⇒ q1101 ⇒ q101 ⇒ q01 ⇒ q1  F mát đạt đến trạng thái này thì sẽ không bao giờ chuyển đến trạng thái khác
Nhận xét: Đối với một xâu vào w, OHD chỉ cho một quá trình đoán được. Trạng thái q1 được gọi là trạng thái bẩy.
nhận duy nhất. Ví dụ 2.6. Chứng minh rằng ngôn ngữ L = { abanbm | m, n > 0 } là
ngôn ngữ chính qui.
2.1.6 Ngôn ngữ được thừa nhận bởi OHD
Để chứng minh một ngôn ngữ là chính qui, ta cần chỉ ra rằng tồn tại
Định nghĩa 2.3. Cho OHD M = (Q, , , q0, F), ngôn ngữ được thừa
OHD thừa nhận ngôn ngữ đó. Thật vậy L được thừa nhận bởi OHD sau:
nhận bởi M, được ký hiệu là L(M), được định nghĩa như sau:
L(M) = {w  * | *(q0, w) = qf, qf  F}. a b a b
q0 q1 q2 q3 q4
Nghĩa là, ngôn ngữ L(M) gồm các xâu w sao cho ô-tô-mát hữu hạn đơn
định M xuất phát từ trạng thái đầu q0, sau khi đọc hết xâu w thì đạt đến một a
trong các trạng thái qf thuộc tập các trạng thái thừa nhận F. b a b
b
Định nghĩa 2.4. Cho OHD M, một ngôn ngữ L = L(M) được gọi là a
ngôn ngữ chính qui (regular language). Hay nói cách khác, ngôn ngữ được a, b q5
thừa nhận bởi một ô-tô-mát hữu hạn đơn định là ngôn ngữ chính qui.
Hình 2.5. OHD thừa nhận L = { abanbm | m,n >0 }
Nhận xét: Đối với một OHD M = (Q, , , q0, F), ứng với một trạng
thái bất kỳ q  Q và một ký hiệu bất kỳ a  , thì hàm dịch chuyển  phải
cho một kết quả xác định, tức là một trạng thái và chỉ một trạng thái p 
Q.

27 28
2.2 Ô-tô-mát hữu hạn không đơn định Như vậy, OHKD cho phép thực hiện sự chuyển trạng thái mà
không đọc ký hiệu vào nào cả.
Một ô-tô-mát hữu hạn không đơn định (non deterministic finite
automata), được viết ngắn gọn OHKD, có thể có nhiều trạng thái khác Tương tự như đối với OHD, một OHKD cũng có thể được mô tả bởi
nhau ở tại một thời điểm. Cũng như OHD, một OHKD gồm một tập hợp hữu biểu đồ dịch chuyển hay bảng dịch chuyển.
hạn các trạng thái, trong đó có một trạng thái đầu, tập các trạng thái thừa Ví dụ 2.7. Xây dựng OHKD thừa nhận ngôn ngữ gồm các xâu trên
nhận, và một tập hợp hữu hạn các ký hiệu vào (bảng chữ). OHKD cũng có bảng chữ {0, 1}, bắt đầu bởi ký hiệu 0 và kết thúc bởi ký hiệu 1. OHKD
một hàm dịch chuyển, được ký hiệu là . được xây dựng trong hình 2.6.
Sự khác nhau cơ bản giữa OHKD và OHD là định nghĩa của hàm dịch
chuyển. Đối với OHKD, hàm dịch chuyển nhận tham số là một trạng thái, 0 q1 1
một ký hiệu vào và trả về một tập hợp, có thể rỗng, các trạng thái. Trong q0 q2
khi, OHD cũng nhận tham số là một trạng thái, một ký hiệu vào, tuy nhiên chỉ 0, 1
trả về đúng một trạng thái.
Hình 2.6. OHKD cho ví dụ 2.7
2.2.1 Định nghĩa hình thức ô-tô-mát hữu hạn không đơn
Giả sử xâu vào w = 01011, quá trình đoán nhận xâu w là như sau:
định
q001011 ⇒ q11011 ⇒ q1011 ⇒ q111 ⇒ q11 ⇒ q2  F
Định nghĩa 2.5. Một ô-tô-mát hữu hạn không đơn định được định
Tuy nhiên, chúng ta có thể dễ dàng nhận thấy rằng, quá trình đoán nhận
nghĩa là một bộ năm
trên chỉ là một trong những quá trình đoán nhận. Các quá trình đoán nhận
M = (Q, , , q0, F) khác thì không thể thừa nhận xâu vào. Nếu xét tất cả các quá trình đoán
trong đó: nhận, ta có:
1. Q là tập hữu hạn các trạng thái, Q = {q0, q1, …, qn};
q001011 ⇒ q11011 ⇒ q1011 ⇒ q111 ⇒ q11 ⇒ q2  F
2.  là bảng chữ vào;
q2011 q21 q1
3. q0  Q là trạng thái đầu;
4. F  Q là tập các trạng thái thừa nhận hay trạng thái cuối; Nhận xét: Đối với một xâu vào w, OHKD có thể có nhiều quá trình
5. hàm dịch chuyển  : Q x {  {}} → tập các tập con đoán nhận khác nhau, trong khi OHD thì chỉ có duy nhất một quá trình
của Q. đoán nhận.

So sánh định nghĩa của OHD và OHKD, chúng ta nhận thấy sự khác OHKD trên có thể biểu diễn dạng bảng chuyển dịch như sau:
biệt giữa hai loại ô-tô-mát hữu hạn là ở định nghĩa hàm dịch chuyển. Định  0 1
nghĩa hàm dịch chuyển của OHD và OHKD có hai sự khác biệt cơ bản là: → q0 {q1} 
q1 {q1} {q1, q2}
- Hàm dịch chuyển của OHD chỉ trả về đúng một trạng thái * q2  
thuộc tập Q, trong khi hàm dịch chuyển OHKD trả về một
tập các trạng thái là tập con của Q. Lưu ý: Kết quả của hàm dịch chuyển là một tập các trạng thái và có thể là
tập rỗng, nghĩa là khi OHKD ở một trạng thái nào đó và đọc ký hiệu vào,
- Hàm dịch chuyển của OHKD đọc , tức là đọc xâu rỗng, thì không tồn tại dịch chuyển tương ứng. Khi đó, ta nói OHKD “bị hóc”,
trong khi hàm dịch chuyển của OHD thì không đọc xâu rỗng. không hoạt động nữa.

29 30
Ví dụ 2.8. Xây dựng OHKD nhận biết ngôn ngữ gồm các xâu có độ dài Ta có:
chẵn không rỗng trên bảng chữ {0, 1}. OHKD được xây dựng trong hình
(q0, a) = (q0, a)  *(q0, a)  *(q0, a)
2.7.
= {q1}  {q2}  {q0} = {q0, q1, q2}.
q2
Ví dụ 2.10. Sử dụng OHKD trong hình vẽ 2.5 để xử lý xâu w =
 0101101. Các bước đoán nhận như sau:

0, 1 1. *(q0, ) = {q0},
2. *(q0, 0) = (q0, 0) = {q1},
0, 1
q0 q1 3. *(q0, 01) = (q1, 1) = {q1, q2},
4. *(q0, 010) = (q1, 0)  (q2, 0) = {q1}   = {q1},
Hình 2.7. OHKD đoán nhận các xâu có độ dài chẵn
5. *(q0, 0101) = (q1, 1) = {q1, q2},
2.2.2 Hàm dịch chuyển mở rộng
6. *(q0, 0101) = (q1, 1)  (q2, 1) = {q1, q2}   = {q1, q2},
Cũng như đối với OHD, chúng ta định nghĩa hàm dịch chuyển mở
7. *(q0, 01011) = (q1, 1)  (q2, 1) = {q1, q2}   = {q1, q2},
rộng, ký hiệu *, khi OHKD ở một trạng thái q nào đó, đọc một xâu w trả về
tập hợp các trạng thái. 8. *(q0, 010110) = (q1, 0)  (q2, 0) = {q1}   = {q1},
Định nghĩa 2.6. Hàm dịch chuyển mở rộng được định nghĩa đệ quy trên 9. *(q0, 0101101) = (q1, 1) = {q1, q2}.
độ dài của xâu w như sau:
2.2.3 Ngôn ngữ được thừa nhận bởi OHKD
1. *(q, ) = {q}, với mọi trạng thái q, nếu OHKD không đọc ký hiệu
Định nghĩa 2.7. Cho OHKD M = (Q, , , q0, F), ngôn ngữ được thừa
vào nào thì sẽ ở lại trạng thái đó.
nhận bởi M, được ký hiệu là L(M), được định nghĩa như sau:
2. Với w = xa, x* và a, giả sử *(q, x) = {p1, p2, …, pk} và
k L(M) = {w  * | *(q0, w)  F  }
( p , a ) = { r , r , ..., r } thì  (q, w) = {r1, r2, …, rn}.
*


i =1
i 1 2 n
Nghĩa là, ngôn ngữ L(M) gồm các xâu w thuộc * sao cho M xuất phát
Lưu ý: Một ký hiệu a  có thể được xem là một xâu *a*. Nghĩa là, từ trạng thái đầu q0, thì *(q0, w) chứa ít nhất một trong các trạng thái thừa
ta có nhận.
* * *
Ví dụ 2.11. Xác định ngôn ngữ được thừa nhận bởi ô-tô-mát hữu hạn
 (q , a ) =  ( q ,  a ). không đơn định trong hình vẽ dưới đây:
Ví dụ 2.9. Cho OHKD trong hình vẽ dưới đây, tính *(q0, a).
 q0 0 q1 1 q2

0, 1
q0 a q1  q2
Hình 2.9. OHKD cho ví dụ 2.11
Hình 2.8. OHKD cho ví dụ 2.9 Ngôn ngữ L = {w  {0, 1}* | w kết thúc bởi xâu 01}. Hay nói một cách
khác, ngôn ngữ L gồm các xâu nhị phân kết thúc bởi xâu 01.
31 32
Ví dụ 2.12. Xây dựng OHKD đoán nhận ngôn ngữ gồm các xâu trên - FD là tập hợp các tập con S của QN sao cho S  FN  . Nghĩa
bảng chữ {0, 1} bắt đầu bởi 000 hoặc kết thúc bởi 111. OHKD được xây là, FD tập hợp các trạng thái trong QD sao cho mỗi trạng thái đó
dựng trong hình 2.10. có chứa ít nhất một trạng thái thừa nhận thuộc FN.
- Đối với mỗi tập T  QN và mỗi ký hiệu a  ,
0 0 0
q1 q2 q3 q4  ( T , a) =  N (q , a)
 D
q trong T
0, 1
q0 Ví dụ 2.13. Cho OHKD N trong hình 2.8 chấp nhận ngôn ngữ gồm các xâu
trên bảng chữ {0, 1} kết thúc bởi 01. Bởi vì tập các trạng thái của N là {q0, q1,
 q5 1 q6 1 1 q2}, số các tập con của tập các trạng thái của N là 23. Như thế, chúng ta có
q7 q8
thể xây dựng bảng dịch chuyển cho OHD như sau:
0, 1  0 1
  
Hình 2.10. OHKD cho ví dụ 2.12 → {q0} {q0, q1} {q0}
{q1}  {q2}
2.3 Sự tương đương giữa OHD và OHKD
* {q2}  
Chúng ta nhận thấy rằng định nghĩa OHD và OHKD là khác nhau: thể {q0, q1} {q0, q1} {q0, q2}
hiện qua hàm dịch chuyển. Ngoài ra, để đoán nhận một ngôn ngữ, việc xây * {q0, q2} {q0, q1} {q0}
dựng OHKD là dễ dàng hơn OHD. Hơn nữa, số trạng thái của một OHD * {q1, q2}  {q2}
thường là rất lớn, trong khi số trạng thái OHKD thường ít hơn. Tuy nhiên, *{q0, q1, q2} {q0, q1} {q0, q2}
chúng ta sẽ thấy rằng OHKD và OHD có vai trò như nhau trong đoán nhận
Lưu ý rằng, mỗi trạng thái của OHD là một tập hợp các trạng thái của
ngôn ngữ. Thật vậy, chúng ta sẽ chỉ ra rằng OHD thực hiện những gì mà
OHKD. Chúng ta có thể đặt tên lại cho các trạng thái này, chẳng hạn {q0}
OHKD thực hiện.
được thay bởi p0, {q1} được thay bởi p1, … Ta có bảng dịch chuyển
2.3.1 Xây dựng OHD từ OHKD như sau:
 0 1
Phương pháp xây dựng OHD từ một OHKD được gọi là xây dựng tập p7 p7 p7
con, bởi vì phương pháp này xây dựng tất cả các tập con của tập các trạng thái → p0 p3 p0
của OHKD. p1 p7 p2
Từ một OHKD N = (QN, , N, q0, FN) chúng ta có thể xây dựng một * p2 p7 p7
OHD D = (QD, , D, {q0}, FD) sao cho L(N) = L(D). Trong đó, bảng chữ p3 p3 p4
vào của OHKD và OHD giống nhau, trạng thái đầu của OHD là tập hợp * p4 p3 p0
{q0}, chỉ gồm trạng thái đầu q0 của OHKD. Các thành phần khác được xây * p5 p7 p2
dựng như sau: * p6 p3 p4
- QD là tập hợp các tập con của QN. Lưu ý rằng, nếu QN có n trạng Trong bảng dịch chuyển trên, chúng ta có thể nhận thấy từ trạng thái
thái thì QD sẽ có 2n trạng thái. Tuy nhiên, thường có các trạng đầu p0 chúng ta chỉ có thể đạt đến các trạng thái p0, p3 và p4, năm trạng
thái không đạt đến được trong QD, các trạng thái này có thể loại thái còn lại là các trạng thái không đạt đến được từ p0. Quá trình đoán
bỏ. Như vậy, QD thường có số trạng thái nhỏ hơn 2n. nhận xâu luôn bắt đầu từ trạng thái đầu q0, trong khi các trạng thái này

33 34
không thể đạt đến từ trạng thái đầu, vậy các trạng thái này vô dụng. Như Lấy qd  QD
thế, chúng ta có thể loại bỏ các trạng thái này. Khi đó, bảng dịch chuyển for each a  
chỉ còn: begin
 0 1 Tính  ( q , a ) =  (q , a) = p
→ p0 p3 p0
D d
qn 
trong
qd
N n d

p3 p3 p4 QD = QD  {pd}
* p4 p3 p0 D = D  {D(qd, a) = pd}
end
Hay biểu diễn dạng biểu đồ trong hình vẽ 2.11.
until Hết qd  QD chưa lấy ra
FD = {qd  QD | qd  FN  }
end

1 0 Ví dụ 2.14. Xây dựng OHD D từ OHKD N trong hình 2.8 theo thuật toán
trên.
0 1
p0 p3 p4 Ban đầu, QD chỉ gồm {q0}.
0 D({q0}, 0) = {q0, q1}.
1  D({q0}, 1) = {q0}.

Hình 2.11. Biểu đồ dịch chuyển của OHD ví dụ 2.13  D({q0, q1}, 0) = N({q0}, 0)   N({q1}, 0) ={q0, q1}.

Chúng ta có thể nhận thấy rằng cách xây dựng OHD từ OHKD như trên  D({q0, q1}, 1) =  N({q0}, 1)   N({q1}, 1) = {q0, q2}.
là mất nhiều thời gian, do phải tính các dịch chuyển cho tất cả 2n các tập  D({q0, q2}, 0) =  N({q0}, 0)   N({q0}, 0) = {q0, q1}.
con của tập các trạng thái của OHKD. Tuy nhiên, như đã minh họa trong
 D({q0, q2}, 1) =  N({q0}, 1)   N({q0}, 1) = {q0}.
ví dụ trên có rất nhiều trạng thái của OHD trong số 2n trạng thái là không
đạt đến được từ trạng thái đầu, nghĩa là các trạng thái đó vô dụng. Vì vậy, Đến bước này, chúng ta không xác định thêm được trạng thái nào mới.
nhằm giảm bớt các tính toán dịch chuyển, chúng ta chỉ tính các dịch Vậy, QD = {{q0}, {q0, q1}, {q0, q2}} và FD = {{q0, q2}}.
chuyển cho các trạng thái có thể đạt đến được từ trạng thái đầu. Để thực So với cách xây dựng OHD trong ví dụ 2.10, ta nhận thấy thuật toán này
hiện điều này, ban đầu chúng ta chỉ tính các dịch chuyển cho trạng thái cho phép thực hiện nhanh hơn và đơn giản hơn.
đầu của OHD, sau đó bổ sung vào OHD các trạng thái mới tính được. Tiếp
tục tính các dịch chuyển cho các trạng thái vừa được đưa vào OHD, nếu Ví dụ 2.15. Xây dựng OHD tương đương với OHKD trong hình vẽ
kết quả cho các trạng thái mới thì bổ sung vào OHD. Lặp lại bước này cho 2.12.
đến khi không có thêm trạng thái mới nào được bổ sung vào OHD. Các
bước này được minh họa bởi thuật toán xây dựng tập con sau: q0 0 q1
ðầu vào: OHKD N = (QN, , N, q0, FN)
ðầu ra: OHD D = (QD, , D, {q0}, FD) 0, 1
begin
Hình 2.12. OHKD cho ví dụ 2.15
QD = {{q0}}
D =  Thực hiện các bước tính các trạng thái của OHD. Chúng ta có:
repeat

35 36
D({q0}, 0) = {q1}, {q1, q2}  {q2} {q1, q2}
 D({q0}, 1) = , Chúng ta đặt p0 = {q0}, p1 = {q0, q1, q2}, p2 = , p3 = {q2} và
p4 = {q1, q2}. Trong đó, p1, p3 và p4 là trạng thái cuối, vì chứa trạng thái
D({q1}, 0) = {q1},
cuối q2 của OHKD. Vậy chúng ta có OHD trong hình vẽ 2.15.
 D({q1}, 1) = {q1},
p0 p1 a
D(, 0) = , a
 D(, 1) = .
Vậy chúng ta có OHD như sau: b, c b
b c
q0 0 q1
a, c
p2 p3
0, 1 a, b, c b
1 a
 c
p4
0, 1
Hình 2.15. OHD tương đương với OHKD trong hình 2.14
Hình 2.13. OHD cho ví dụ 2.15
2.3.2 Sự tương đương giữa OHKD và OHD
Ví dụ 2.16. Xây dựng OHD tương đương với OHKD trong hình vẽ
2.14. Trong mục trên, chúng ta vừa chỉ ra cách xây dựng OHD từ OHKD,
tuy nhiên chúng ta cần phải chứng minh rằng OHD được xây dựng phải
q0 a q2 thừa nhận cùng một ngôn ngữ với OHKD. Thật vậy, chúng ta có định lý
dưới đây.
a b
a  Định lý 2.1. Nếu D = (QD, , D, {q0}, FD) là một OHD được xây dựng từ
OHKD N = (QN, , N, q0, FN) theo thuật toán xây dựng tập con thì L(N) =
q1 L(D).
c Chứng minh
Hình 2.14. OHKD cho ví dụ 2.16 Để chứng minh L(N) = L(D), chúng ta sẽ chứng minh bằng phương
pháp quy nạp trên độ dài xâu w rằng
Áp dụng thuật toán xây dựng tập con, chúng ta lập bảng dịch chuyển
như sau: *D({q0}, w) = *N(q0, w).
 a b c Lưu ý rằng hàm * trả về một tập hợp các trạng thái trong QN, *D thì
→ {q0} {q0, q1, q2}   xem tập hợp này như là một trạng thái của QD, trong khi *N thì xem tập hợp
{q0, q1, q2} {q0, q1, q2} {q2} {q1, q2} này như là một tập con trong QN.
   
{q2}  {q2} 

37 38
Bước cơ sở: |w| = 0, nghĩa là xâu w = . Theo các định nghĩa của hàm 1. Trạng thái đầu q0 thực hiện dịch chuyển lên chính nó khi đọc bất
dịch chuyển mở rộng cho OHD và OHKD, thì *D({q0}, ) và *N(q0, ) đều kỳ một ký tự nào thuộc bảng chữ (tạo nên văn bản). Trạng thái q0
bằng {q0}. sẽ phải “đoán” sự bắt đầu của một từ hay không.
Bước quy nạp: Giả sử *D({q0}, w) = *N(q0, w) đúng khi |w| = n, cần 2. Đối với mỗi từ w = a1a2 … an, OHKD sử dụng n trạng thái q1,
chứng minh cho trường hợp |w| = n + 1. Khi đó, xâu w có dạng xa, với q2, …, qn để đoán nhận. Khi OHKD đọc a1 thì có dịch chuyển từ
x  *, a   và |x| = n. Theo giả thuyết quy nạp, *D({q0}, x) = *N(q0, x). q0 đến q1, khi OHKD đọc a2 thì có dịch chuyển từ q1 đến q2, …
Giả sử tập kết quả của *D({q0}, x) = *N(q0, x) là tập hợp {p1, p2, …, pk}. Trạng thái qn là trạng thái thừa nhận và chỉ ra rằng từ
Theo định nghĩa hàm dịch chuyển mở rộng cho OHKD, chúng ta có w = a1a2 … an được tìm thấy.
Ví dụ 2.17. Xây dựng OHKD nhận biết các từ khóa nfa và dfa. Giả sử
 ( q 0, w )=  ( p i , a)
*
N k văn bản gồm các từ trên bảng chữ  = {a, b, c, …, z}.
i= 1
Dựa trên các luật xây dựng OHKD vừa trình bày ở trên, chúng ta xây
Theo định nghĩa hàm dịch chuyển cho OHD, chúng ta có dựng OHKD như sau:
*D({q0}, w) = D(*D({q0}, x), a) = D({p1, p2, …, pk}, a).
S f 3 a 4
Mặt khác, theo thuật toán xây dựng tập con, thì n
 ( { p , p ,..., p }, a  ( p ,a)
)=
D 1 2 k
k i
i=1 1
Vậy chúng ta kết luận *D({q0}, w) = *N(q0, w) với |w| = n + 1. d
Chúng ta nhận thấy rằng N và D thừa nhận w khi và chỉ khi f a
5
*D({q0}, w) hoặc *N(q0, w) chứa một trạng thái thuộc FN. Như vậy, chúng 6 7
ta vừa chứng minh L(N) = L(D).
Hình 2.16. OHKD nhận biết các từ nfa và dfa
2.4 Ứng dụng của ô-tô-mát hữu hạn Nhận xét: Quá trình OHKD nhận biết chưa thật hiệu quả, vì từ trạng
Chúng ta nhận thấy rằng ô-tô-mát hữu hạn được ứng dụng rất hiệu quả thái đầu OHKD phải “đoán” khi nào là bắt đầu một từ. Nếu quá trình dự
trong tìm kiếm từ hay chuỗi trong văn bản: chẳng hạn như tìm kiếm thông đoán sai, thì phải quay lui.
tin trên web, tìm kiếm trong từ điển… Trong mục này, chúng ta sẽ xem Ví dụ 2.18. Xây dựng OHKD nhận biết các tên biến trong ngôn ngữ lập
xét một số ví dụ ứng dụng của ô-tô-mát hữu hạn trong tìm kiếm từ hay trình C. Trong ngôn ngữ C, quy ước đặt tên biến như sau:
chuỗi.
− Chỉ sử dụng các ký tự: {a, b, …, z, A, B, … Z, 0, 1, …, 9, _}, hay
2.4.1 OHKD dùng để tìm kiếm từ chúng ta có thể viết ngắn gọn: {a-z, A-Z, 0-9,_}.
− Tên biến không được bắt đầu bởi một chữ số từ 0 đến 9.
Giả sử có một tập hợp các từ, chúng ta muốn tìm sự xuất hiện của các từ − Tên biến không được rỗng.
đó trong một văn bản. Trong trường hợp này, chúng ta sẽ xây dựng một
OHKD nhận biết một từ khi nó đạt đến một trong các trạng thái thừa nhận. Chúng ta xây dựng OHKD như trong hình vẽ 2.17.
Tại mỗi thời điểm OHKD sẽ đọc một ký tự của văn bản. OHKD như thế
q0 a-z, A-Z, _ q1
được xây dựng như sau:

39 a-z, A-Z, 0-9, _ 40


Hình vẽ 2.17. OHKD nhận biết các tên biến − Nếu một dấu nháy kép xuất hiện bên trong một chuỗi ký tự thì
Ví dụ 2.19. Xây dựng OHKD nhận biết các số thập phân. Mỗi số thập được biểu diễn . Ví dụ, chuỗi ký tự abbbb biểu diễn
phân gồm các thành phần theo thứ tự sau: chuỗi abbbb.

1. Một dấu + hoặc -, hoặc có thể không có dấu; OHKD trong hình vẽ dưới nhận biết các chuỗi ký tự.

2. Một dãy các chữ số;  


q0 q1 q2
3. Một dấu chấm; 
a-z, A-Z
4. Một dãy các chữ số. Dãy các chữ số này hoặc dãy các chữ số ở
mục 2 có thể rỗng, tuy nhiên ít nhất một trong hai dãy các chữ Hình 2.19. OHKD nhận biết các chuỗi ký tự
số này phải khác rỗng.
2.4.2 OHD dùng để tìm kiếm từ
Chúng ta xây dựng OHKD như trong hình vẽ 2.18.
Với cách xây dựng OHKD như trên, chúng ta có thể sử dụng thuật đoán
0, 1, … 9 0, 1, … 9
chuyển đổi OHKD thành OHD để xây dựng OHD tương đương.
q2
Ví dụ 2.21. Xây dựng OHD từ OHKD trong ví dụ 2.20. Ví dụ này được
q0 , +, - q1 0, 1, … 9 q4 q5 xem như bài tập.

Đối với OHD, chúng ta dễ dàng nhận thấy rằng quá trình đoán nhận
0, 1, … 9 q3 hiệu quả hơn vì không có sự quay lui.

Hình 2.18. OHKD nhận biết các các số thập phân 2.5 Bài tập chương 2
Hay chúng ta có thể biểu diễn OHKD dạng bảng dịch chuyển như sau: Bài 2.1. Cho ô-tô-mát hữu hạn M với biểu đồ dịch chuyển trong hình vẽ
  +, - 0, 1, …, 9 2.15.
→ q0 {q1} {q1}  
q1   {q2} {q1, q3} 1
0 0
q2    {q4}
q0 q1 q2 q3
q3   {q4}  0 1
q4 {q5}   {q4} 0
* q5     1 1 1
1
Ví dụ 2.20. Xây dựng OHKD đoán nhận các chuỗi ký tự trong một 0 1
ngôn ngữ lập trình. Mỗi ký tự của chuỗi có thể là các ký hiệu: {a, b, …, z, q4 q5
A, B, … Z, }, hay chúng ta có thể viết ngắn gọn: {a-z, A-Z, }. Tập hợp 0
các chuỗi ký tự được định nghĩa như sau:
Hình 2.20. OHD cho bài tập 1.
− Mỗi chuỗi ký tự đều phải bắt đầu và kết thúc bởi ký hiệu  (dấu
a. Hãy cho biết M có phải là OHD không ?
nháy kép).
b. Hãy sử dụng M đoán nhận các xâu sau: 0001, 101010100 và
1000010101.

41 42
Bài 2.2. Mô tả một cách không hình thức ngôn ngữ được đoán nhận bởi Bài 2.6. Hãy xây dựng các OHD đoán nhận các ngôn ngữ trên bảng
OHD sau: chữ {a, b} sau:
 0 1 a. Tập các xâu chứa ít nhất xâu con aba.
→ q0 q1 q0
q1 q2 q0 b. Tập các xâu có độ dài lẻ.
* q2 q2 q2 c. Tập các xâu bắt đầu bởi ký hiệu a, chứa ít nhất xâu con bb và
Bài 2.3. Cho OHD trong hình vẽ 2.21, hãy mô tả ngôn ngữ được đoán kết thúc bởi ký hiệu a.
nhận bởi OHD. d. Tập các xâu bắt đầu bởi aba hoặc kết thúc bởi bab.
1 0 0
Bài 2.7. Chứng minh các ngôn ngữ sau là chính qui:

0 1 0 0 a. L1 = {abnabm | n,m  0}.


q3 q3 q3 q5 q6 b. L2 = {w  {0, 1} | w không chứa xâu con 11 nào cả}.
1
1 Bài 2.8. Chuyển các OHKD sau thành OHD:
Hình 2.21. OHD cho bài tập 3. a.
 0 1
Bài 2.4. Hãy mô tả ngôn ngữ được đoán nhận bởi OHD trong hình →p {p, q} {p}
0 q {r} {r}
q0 q1 r {s} 
0 *s {s} {s}
1 1 b.
1 1  0 1
0 →p {q, s} {q}
q3 q2 *q {r} {q, r}
0 r {s} {p}
*s  {p}
vẽ 2.22.
c.
Hình 2.22. OHD cho bài tập 4.
 0 1
Bài 2.5. Hãy xây dựng các OHD đoán nhận các ngôn ngữ trên bảng →p {p, q} {p}
chữ {0, 1} sau: q {r, s} {t}
a. Tập các xâu có độ dài chia hết cho 3. r {p, r} {t}
*s  
b. Tập các xâu kết thúc bởi 00. *t  
c. Tập các xâu chứa ba ký hiệu 0 liên tiếp nhau. d.
d. Tập các xâu bắt đầu hoặc kết thúc (hoặc cả hai) bởi 01.   A b C
→p {q, r}  {q} {r}

43 44
q  {p} {r} {p, q}
*r    
Bài 2.9. Xây dựng các OHKD đoán nhận các ngôn ngữ sau: Chương 3. Biểu thức chính quy
a. Tập các xâu trên bảng chữ {0, 1, …, 9} không bắt đầu bởi ký
hiệu 0.
b. Tập các xâu trên bảng chữ {0, 1, …, 9} biểu diễn các số tự Chúng ta đã tìm hiểu ô-tô-mát hữu hạn là cơ chế mô tả ngôn ngữ chính
nhiên chia hết cho 5. quy. Ngoài ra, còn có những cách khác để mô tả ngôn ngữ chính quy.
Chúng ta sẽ tìm hiểu trong chương này một trong những cách đó: biểu
Bài 2.10. Xây dựng các OHKD đoán nhận các từ sau:
thức chính quy.
a. 101, 110 với bảng chữ là {0, 1}.
b. abc, bcb, caba với bảng chữ là {a, b, c}. 3.1 Biểu thức chính quy
c. Xây dựng các OHD tương đương với các OHKD trong câu a và Chúng ta sẽ thấy rằng biểu thức chính quy (regular expresssion) cho
phép định nghĩa cùng loại ngôn ngữ được định nghĩa bởi ô-tô-mát hữu
câu b.
hạn: ngôn ngữ chính quy. Tuy nhiên, biểu thức chính quy thực hiện điều mà
ô-tô-mát không làm được: mô tả một cách tường minh các xâu thuộc ngôn
ngữ. Biểu thức chính quy được sử dụng như là ngôn ngữ vào của một số hệ
thống, chẳng hạn:
- Câu lệnh grep trong hệ điều hành Unix hay Linux. Câu lệnh này sử
dụng một tham số đầu vào có dạng biểu thức chính quy để tìm kiếm
các xâu chữ trong các tệp tin văn bản.
- Câu lệnh sed trong hệ điều hành Unix hay Linux. Câu lệnh này
cũng sử dụng một tham số đầu vào có dạng biểu thức chính quy để
xử lý (sửa đổi, thay thế, …) trên tệp văn bản.
- Sản sinh bộ phân tích từ vựng Lex. Bộ phân tích từ vựng là một
thành phần của chương trình dịch nhằm phân tích chương trình
nguồn thành các đơn vị từ vựng (token), như từ khóa, biến, số, ….
Bộ phân tích từ vựng sử dụng dạng biểu thức chính quy để mô tả
các đơn vị từ vựng, và sau đó sinh ra OHD tương ứng để nhận biết
dữ liệu vào.

3.1.1 Định nghĩa hình thức của biểu thức chính quy
Định nghĩa 3.1. Cho bảng chữ , biểu thức chính quy (BTCQ) trên
 được định nghĩa đệ quy như sau:
1.  là biểu thức chính quy,
2.  là biểu thức chính quy,
45 46
3. a  , a là biểu thức chính quy, Ví dụ 3.3. Xây dựng biểu thức chính quy biểu diễn ngôn ngữ L gồm
các xâu trên bảng chữ {a, b} chứa ít nhất một ký hiệu a và ít nhất một ký hiệu
4. Nếu r và s là các biểu thức chính quy thì (r + s), (rs), (r)* là các
b.
biểu thức chính quy.
Chúng ta có thể nhận thấy rằng, ngôn ngữ L sẽ gồm tập hợp của hai
Lưu ý: Chúng ta có thể viết (r  s) thay vì viết (r + s).
ngôn ngữ L1 và L2, mà L1 gồm các xâu có ít nhất một ký hiệu a và ít nhất một
Ví dụ 3.1. Xem xét các biểu thức chính quy sau: ký hiệu b mà ký hiệu a đứng trước ký hiệu b, còn L2 gồm các xâu có ít nhất
- (a + b + c) là biểu thức chính quy biểu diễn ba xâu a, b, c trên một ký hiệu a và ít nhất một ký hiệu b mà ký hiệu b đứng trước ký hiệu a.
bảng chữ {a, b, c}. Việc xây dựng biểu thức chính quy biểu diễn ngôn ngữ L1 và L2 là tương tự
nhau. Chúng ta sẽ xây dựng biểu thức chính quy cho L1.
- (a + b)* là biểu thức chính quy biểu diễn mọi xâu trên bảng
chữ {a, b}. Chúng ta dễ dàng nhận thấy, L1 gồm các xâu có dạng: w1aw2bw3. Trong đó
w1, w2, w3 là xâu bất kì trên {a, b}. Một xâu bất kỳ trên {a, b} có thể dễ dàng
- (aa*bb*) là biểu thức chính quy biểu diễn các xâu bắt đầu bằng biểu diễn bởi biểu thức chính quy: (a + b)*. Vậy biểu thức chính quy biểu
một số ký hiệu a, tiếp theo là một số ký hiệu b, trong đó a và b diễn L1 là r1 = (a + b)*a(a + b) *b(a + b) *. Tương tự, ta có biểu thức chính
đều có mặt ít nhất một lần. quy biểu diễn L2 là r2 = (a + b)*b(a + b) *a(a + b) *. Cuối cùng, biểu thức
- (b + )(a + ab)* là biểu thức chính quy biểu diễn các xâu trên chính quy biểu diễn L là:
bảng chữ {a, b} không chứa bb.
r1 + r2 = (a + b)*a(a + b) *b(a + b) * + (a + b)*b(a + b) *a(a + b) *.
Định nghĩa 3.2. Ngôn ngữ L(r) được biểu diễn bởi biểu thức chính quy
r bất kỳ là được xây dựng theo các quy tắc sau: 3.1.2 Độ ưu tiên các phép toán trên biểu thức chính quy
1. L() = , Độ ưu tiên của các phép toán trên biểu thức chính quy được quy định
theo thứ tự sau: phép bao đóng (*) có độ ưu tiên cao nhất, sau đó đến phép nối
2. L() = {}, (.) và cuối cùng có độ ưu tiên thấp nhất là phép hợp (+ hoặc ).
3. L(a) = {a} với a  , Chúng ta có thể xem biểu thức chính quy tương tự như biểu thức số học,
Cho r và s là các biểu thức chính quy, trong đó phép hợp được xem như phép cộng, phép nối được xem như phép
nhân và phép bao đóng được xem như phép lũy thừa.
4. L(r + s) = L(r)  L(s),
Ví dụ 3.4. Cho biểu thức chính quy r = 10* + 1, chúng ta có thể nhóm lại
5. L(rs) = L(r)L(s),
theo thứ tự ưu tiên như sau r = (1(0*)) + 1.
6. L((r)*) = (L(r))*.
3.1.3 Các tính chất đại số của biểu thức chính quy
Ví dụ 3.2. Xây dựng biểu thức chính quy biểu diễn ngôn ngữ gồm các xâu
trên bảng chữ {a, b} chứa ít nhất xâu aba. Các biểu thức chính quy có thể được rút gọn. Để thực hiện điều đó,
chúng ta sử dụng một số các tính chất đại số của các biểu thức chính quy.
Xâu chứa ít nhất aba có thể được viết dưới dạng uabav trong đó u và v là
Các tính chất đại số của biểu thức chính quy cũng tương tự như các tính
các xâu bất kỳ trên {a, b}. Như vậy, biểu thức chính quy cho tập các xâu
chất đại số của các biểu thức số học.
này là:
Cho r, s và t là các biểu thức chính quy.
(a + b)*aba(a + b)*.
Tính chất giao hoán (commutativity)
r+s=s+r

47 48
Tính chất kết hợp (associativity) trong đó u0, u1, v0, v1, w0, w1 là các xâu không chứa 00 và 11, u0 kết
r + (s + t) = (r + s) + t thúc bởi 0, u1 kết thúc bởi 1, v0 bắt đầu bởi 0, v1 bắt đầu bởi 1, w0 bắt đầu
bởi 0 và kết thúc bởi 1, w1 bắt đầu bởi 1 và kết thúc bởi 0.
r(st) = (rs)t
Kết hợp các trường hợp (2), (4), (6) và sử dụng tính chất phân phối ta
Tính chất phân phối (distributivity)
có:
r(s + t) = rs + rt
u10 + u100v1 + u100w111v0 = u10( + 0v1 + 0w111v0).
(r + s)t = rt + st
Chúng ta có thể xây dựng biểu thức chính quy của các xâu sau:
Một số tính chất khác
u10 = ( + 0)(10)*
+r=r+=r r = r = r
0v1 = (01)*( + 0)
r = r =  r+r=r
0w11 = (01)*
* *
(r ) = r *
* = 
1v0 = (10)*( + 1)
 =* + *
r = rr = r r *
Vậy:
r* = r+ +  (r*s*)* = (r + s)*
u10( + 0v1 + 0w111v0)
Lưu ý rằng một ngôn ngữ có thể được biểu diễn bởi nhiều biểu thức
= ( + 0)(10)*( + (01)*( + 0) + (01)*(10)*( + 1))
chính quy khác nhau, nghĩa là các biểu thức chính quy khác nhau tương
đương với nhau. = ( + 0)(10)*( + (01)* + (01)*0 + (01)*(10)*( + 1))
Ví dụ 3.5. a*(a + b)* = (a + ba*)*. Lưu ý rằng  + (01)* = (01)*. Vậy:
Thật vậy, chúng ta sẽ chỉ ra rằng cả hai vế trên bằng (a + b)*. u10( + 0v1 + 0w111v0)
Vì (a + b)* chứa mọi xâu trên {a, b}, nên (a + b)*  a*(a + b)* và (a + = ( + 0)(10)*((01)* + (01)*0 + (01)*(10)*( + 1))
b)*  (a + ba*)*. Như thế, chúng ta chỉ còn cần chỉ ra cả hai vế chứa (a + = ( + 0)(10)*(01)*( + 0 + (10)*( + 1))
b) . Bởi vì,   a*, nên a*(a + b)*  (a + b)*. Cũng như thế, vì b  ba*, nên
*

(a + ba*)*  (a + b)*. Vậy, a*(a + b)* = (a + ba*)*. Tương tự như vậy, kết hợp (3), (5) và (7), ta có:
Ví dụ 3.6. Xác định biểu thức chính quy biểu diễn tập L gồm các xâu nhị u00 + u011v0 + u011w000v1
phân chứa nhiều nhất hai số 00 đi liền nhau và nhiều nhất hai số 11 đi liền = ( + 1)(01)*(10)*( + 1 + (01)*( + 0))
nhau.
Vậy cuối cùng, ta có biểu thức chính quy biểu diễn các xâu nhị phân
Một xâu w trong tập L có thể có một trong các dạng sau: chứa nhiều nhất hai số 00 đi liền nhau và nhiều nhất hai số 11 đi liền nhau
(1) , là:
(2) u10, (4) u100v1, (6) u100w111v0,  + ( + 0)(10)*(01)*( + 0 + (10)*( + 1))
(3) u00, (5) u011v0, (7) u011w000v1, + ( + 1)(01)*(10)*( + 1 + (01)*( + 0)).

49 50
3.2 Biểu thức chính quy và ô-tô-mát hữu hạn Trong hình 3.1, OHKD trong phần a) không đoán nhận bất cứ xâu vào
nào, nghĩa là ngôn ngữ L() = . OHKD trong phần b) đoán nhận ngôn
Chúng ta đã định nghĩa ngôn ngữ chính quy được thừa nhận bởi ô-tô-
ngữ chỉ gồm xâu , nghĩa là ngôn ngữ L() = {}. OHKD trong phần c)
mát hữu hạn đơn định hoặc ô-tô-mát hữu hạn không đơn định. Trong phần này
đoán nhận ngôn ngữ chỉ gồm xâu a, nghĩa là ngôn ngữ L(a) = {a}. Chúng ta
chúng ta sẽ chỉ ra rằng biểu thức chính quy cũng biểu diễn các ngôn ngữ
nhận thấy rằng các OHKD này tương ứng với các biểu thức chính quy cơ bản
chính quy.
,  và a. Như thế, giả thuyết quy nạp đúng.
Để chứng minh rằng biểu thức chính quy biểu diễn các ngôn ngữ chính
quy, chúng ta cần phải chỉ ra:
1. Một ngôn ngữ được định nghĩa bởi một biểu thức chính quy thì  r 
cũng được định nghĩa bởi một ô-tô-mát hữu hạn. Để chứng minh
điều này, chúng ta sẽ sử dụng OHKD.
2. Một ngôn ngữ được định nghĩa bởi một ô-tô-mát hữu hạn thì cũng  s 
được định nghĩa bởi một biểu thức chính quy. Để chứng minh điều
này, chúng ta sẽ sử dụng OHD. a)

3.2.1 Xây dựng ô-tô-mát hữu hạn từ biểu thức chính quy

Định lý 3.1. Một ngôn ngữ được định nghĩa bởi biểu thức chính quy thì r s
cũng được định nghĩa bởi ô-tô-mát hữu hạn.
b)
Nghĩa là, một ngôn ngữ được định nghĩa bởi biểu thức chính quy là
ngôn ngữ chính quy.

Chứng minh: Giả sử L = L(r) với r là biểu thức chính quy. Chúng ta chỉ
ra rằng L = L(M) với M là ô-tô-mát hữu hạn không đơn định mà:
 
1. Chỉ có một trạng thái thừa nhận hay trạng thái cuối. r
2. Không có cung nào đi vào trạng thái đầu.
3. Không có cung nào đi ra khỏi trạng thái cuối. 
Chúng ta sẽ chứng minh định lý bằng quy nạp trên biểu thức chính quy
r, dựa theo định nghĩa đệ quy biểu thức chính quy trong mục 3.1. c)
Bước cơ sở: Để chứng minh bước này, chúng ta cần xây dựng OHKD
Hình 3.2. Các OHKD tướng ứng các biểu thức chính quy r+s, rs, r *
tương ứng với các biểu thức chính quy cơ bản là ,  và a.
Bước quy nạp: Chứng minh bước này được minh họa trong hình
 a 3.2. Chúng ta giả sử định lý đúng với các biểu thức chính quy con của một
biểu thức chính quy đã cho, nghĩa là các ngôn ngữ tương ứng với các biểu
thức chính quy con là được thừa nhận bởi các OHKD với chỉ một trạng thái
a) b) c)
cuối. Có bốn trường hợp như sau:
Hình 3.1. Các OHKD tương ứng với các biểu thức chính quy ,  và a

51 52
1. Biểu thức chính quy là r + s với r và s là các biểu thức chính quy Chúng ta sẽ xây dựng trước hết các OHKD tương ứng các biểu thức
con. OHKD trong hình vẽ 3.2 a) được sử dụng. Thật vậy, bắt đầu chính quy con 0, 1, (0 + 1), 0*, 00*, 00* +  trong các hình vẽ dưới đây.
bởi trạng thái đầu mới chúng ta có thể đến một trong hai trạng thái
đầu của OHKD tương ứng r hoặc của OHKD tương ứng s. Khi 0 1
chúng ta đạt đến một trong các trạng thái thừa nhận của các OHKD
tương ứng r hoặc s, thì thừa nhận tương ứng các xâu thuộc L(r) Hình 3.3. Các OHKD tương ứng biểu thức 0, 1
hoặc L(s), chúng ta tiếp tục đạt đến trạng thái cuối mới bởi dịch
chuyển-. Như thế, ngôn ngữ được thừa nhận bởi OHKD trong 0
 
hình vẽ 3.2 a) là L(r)  L(s).
2. Biểu thức chính quy là rs với r và s là các biểu thức chính quy con.
OHKD tương ứng với phép nối hai biểu thức được chỉ ra trong
 1 
hình vẽ 3.2 b). Trong đó, trạng thái đầu của OHKD thứ nhất sẽ trở
thành trạng thái đầu của OHKD mới và thạng thái cuối của OHKD Hình 3.4. OHKD tương ứng biểu thức 0 + 1
thứ hai sẽ trở thành trạng thái cuối của OHKD mới. Chúng ta dễ 
dàng nhận thấy rằng, bắt đầu bởi trạng thái đầu đi qua OHKD
tương ứng r sẽ thừa nhận các xâu thuộc L(r) và tiếp tục đi qua  0 
OHKD tương ứng s sẽ thừa nhận các xâu thuộc L(s). Như thế,
OHKD tương ứng rs thừa nhận các xâu thuộc ngôn ngữ L(r)L(s).
3. Biểu thức chính quy là r* với r là biểu thức chính quy con. Chúng
ta sử dụng OHKD trong hình vẽ 3.2 c). OHKD này cho phép: 
a. Đi trực tiếp từ trạng thái đầu đến trạng thái cuối theo cung
có nhãn , nghĩa là OHKD thừa nhận xâu  thuộc L(r*), với Hình 3.5. OHKD tương ứng biểu thức 0*
biểu thức chính quy r bất kỳ. 
b. Từ trạng thái đầu của OHKD tương ứng r, có thể đi qua
OHKD tương ứng r một hoặc nhiều lần và sau đó đạt đến 0  0 
trạng thái cuối. Như thế, OHKD sẽ chấp nhận các xâu
thuộc L(r), L(r)L(r), L(r)L(r)L(r), …, nghĩa là OHKD sẽ
chấp nhận tất cả các xâu thuộc L(r*), ngoại trừ xâu  đã
được thừa nhận khi đi trực tiếp từ trạng thái đầu đến trạng 
thái cuối như đã đề cập trong mục 3a.
4. Biểu thức (r) với r là là biểu thức chính quy con. OHKD tương Hình 3.6. OHKD tương ứng biểu thức 00 *
ứng r cũng sẽ là OHKD tương ứng (r), bởi vì các dấu ngoặc không
làm thay đổi ngôn ngữ được định nghĩa.
Ví dụ 3.4. Xây dựng OHKD tương ứng với biểu thức chính quy (0 +
1)(00* + ).

53 54
Định lý 3.2. Nếu L = L(M) với OHD M nào đó, thì tồn tại biểu thức
 chính quy r sao cho L = L(r).
0  
0  Chứng minh: Giả sử rằng M có n trạng thái {1, 2, …, n}, với n là số
(k )
 nguyên dương. Đặt r ij là biểu thức chính quy biểu diễn ngôn ngữ gồm
các xâu w sao cho w là nhãn của đường đi từ trạng thái i đến trạng thái j
  trong M, và đường đi không đi qua trạng thái trung gian lớn hơn k. Lưu ý
rằng trạng thái đầu và cuối của đường đi không phải là trạng thái trung
 
gian, vì vậy không có ràng buộc i và j phải nhỏ hơn hoặc bằng k.
(k )

Hình 3.7. OHKD tương ứng biểu thức 00* +  Để xây dựng biểu thức r ij , chúng ta sử dụng phương pháp quy nạp,
bắt đầu với k = 0, và cuối cùng đạt đến k = n. Lưu ý rằng khi k = n không
Cuối cùng, chúng ta có OHKD trong hình 3.8 tương ứng biểu thức có ràng buộc trên đường đi được biểu diễn, bởi vì không có trạng thái nào
chính quy (0 + 1)(00* + ). lớn hơn n.
0 Bước cơ sở: Khi k = 0. Bởi vì tất cả các trạng thái đều được đánh số từ
 
1 trở đi, ràng buộc của r ) (0 sẽ dẫn đến đường đi được biểu diễn không
ij
chứa bất kỳ trạng thái trung gian nào. Chỉ có hai loại đường đi thỏa mãn
 điều kiện:
 1
(1) Một cung từ trạng thái i đến trạng thái j.

 (2) Một đường đi có độ dài bằng 0 chỉ chứa trạng thái i.


0   Nếu i  j, thì chỉ có thể trường hợp (1) xảy ra. Chúng ta cần phải xem
0  xét OHD M và tìm các ký hiệu a mà dịch chuyển từ trạng thái i đến trạng thái
 j có nhãn là a. Có các khả năng sau xảy ra:
(0 )
  (a) Nếu không tồn tại ký hiệu a như thế, thì r ij = .

 (b) Nếu tồn tại đúng một ký hiệu a như thế, thì r(0 ) = a.
 ij

(c) Nếu tồn tại các ký hiệu a1, a2, …, ak là nhãn các cung từ trạng
Hình 3.8. OHKD tương ứng biểu thức (0 + 1)(00* + ) thái i đến trạng thái j, thì r ij(0) = a + a + … + a .
1 2 k
Lưu ý rằng ô-tô-mát hữu hạn trên có thể được rút gọn đơn giản hơn
bằng cách loại bỏ các dịch chuyển-. Nếu i = j, thì chỉ có thể trường hợp (2) xảy ra, các đường đi có độ dài
bằng 0 chỉ chứa trạng thái i, tức là vòng lặp trên chính trạng thái i. Đường
3.2.2 Xây dựng biểu thức chính quy từ ô-tô-mát hữu hạn đi có độ dài bằng 0 được biểu diễn bởi biểu thức chính quy , bởi vì không
có ký hiệu nào trên đường đi đó. Như thế, chúng ta thêm  vào các biểu
Ngược lại, chúng ta cũng có thể xây dựng biểu thức chính quy tương thức tính được trong (a), (b) và (c) ở trên. Nghĩa là, trong trường hợp (a)
ứng với ô-tô-mát hữu hạn cho một ngôn ngữ. (0 ) (0 )
r ij = , trong trường hợp (b) r ij =  + a và trong trường hợp (c)
r (0ij)=  + a1 + a2 + … + ak.

55 56
Bước quy nạp: Giả sử tồn tại đường đi từ trạng thái i đến trạng thái j quy biểu diễn ngôn ngữ đoán nhận bởi OHD M là hợp của tất cả các
(n )
qua các trạng thái trung gian không lớn hơn k. Có hai trường hợp cần xem r 1 j với j  F.
xét:
Ví dụ 3.5. Chuyển OHD trong hình 3.10 thành biểu thức chính quy
(1) Đường đi không đi qua trạng thái k. Trong trường hợp này, nhãn tương ứng. OHD này đoán nhận ngôn ngữ trên {0, 1} chứa ít nhất một ký
( k− 1 )
của đường đi là thuộc ngôn ngữ của r ij hiệu 0.
1 0,1
(2) Đường đi qua trạng thái k ít nhất một lần. Như thế, chúng ta có thể
chia đường đi thành nhiều đoạn, như trong hình 3.9. Đoạn đầu đi từ
0
trạng thái i đến trạng thái k không đi qua trạng thái trung gian k, 1 2
đoạn cuối đi từ trạng thái k đến trạng thái j không đi qua trạng thái
trung gian k, các đoạn ở giữa đi từ trạng thái k đến chính nó nhưng Hình 3.10. OHD đoán nhận các xâu chứa ít nhất một ký hiệu 0
không đi qua trạng thái trung gian k. Lưu ý rằng nếu đường đi qua
trạng thái k chỉ một lần, thì không có các đoạn giữa, chỉ có đoạn từ i Chúng ta sẽ xây dựng biểu thức chính quy dựa theo định lý 3.2. Các
(0)
đến k và từ k đến j. Tập các nhãn của tất cả các đường đi này được biểu thức r được xây dựng trong bước cơ sở gồm:
ij
(k − 1) (k − 1) * (k − 1) (0 )
biểu diễn bởi biển thức chính quy r (r )r . Nghĩa là, biểu
ik kk kj
r (011) =  + 1
thức thứ nhất biểu diễn phần của đường đi từ i đến k lần đầu tiên, 12 = 0

biểu thức thứ hai biểu diễn phần của đường đi từ k đến chính nó, có thể r (0 )
21 = 
lặp nhiều lần, và biểu thức thứ ba biểu diễn phần của đường đi rời k
cuối cùng đến trạng thái j. (0 )
22 =  + 0 +1
r (0 )

r
i k k k j Chẳng hạn, r 11 có nhãn  vì dịch chuyển này bắt đầu và kết thúc trên
(0 )
cùng trạng thái 1. r 11 có nhãn 1 vì có dịch chuyển trên chính trạng thái 1
khi đọc 1. Hay r(0 ) rỗng, vì không có dịch chuyển từ trạng thái 2 đến trạng
( k− 1 ) (k − 1 ) ( k− 1 )
( r kk )*
21
r ik r kj thái 1.
Hình 3.9. Đường đi từ i đến j chia thành ba đoạn (1)
Tiếp theo, chúng ta xây dựng các biểu thức r ij theo luật đã được trình
Kết hợp các biểu thức của hai trường hợp trên, chúng ta có biểu thức: bày trong bước quy nạp khi chứng minh định lý 3.2:
( k) (k − 1 ) (k − 1) (k − 1 ) * ( k− 1) (1) (0 ) (0) (0 ) * (0)
r ij = r ij + r ik (r kk
) r kj r =r +r (r ) r
ij ij i1 11 1j
với các nhãn của tất cả các đường đi từ trạng thái i đến trạng thái j mà Thay thế các r ij(0) đã được xây dựng ở bước cơ sở và rút gọn biểu thức
không đi qua các trạng thái trung gian lớn hơn k. Như thế, mỗi r (k ) chỉ phụ
ij
chính quy, chúng ta có:
thuộc vào các biểu thức với chỉ số nhỏ hơn k-1. (1)
* *

Cuối cùng, chúng ta có r (n) r 11 =  + 1 (  + 1 )(  + 1 ) (  + 1 ) = 1


ij
+ * *
với mọi i và j. Chúng ta có thể giả sử rằng,
(0)
trạng thái 1 là trạng thái đầu và tập các trạng thái cuối F. Biểu thức chính r 12 = 0 + (  + 1 )(  + 1 ) 0 = 1 0
(0)
r 21
5
= 
+
5
( 8

+
1
)
*
(

+
1
)
=

r(0 ) =  + 0 + 1 + ( + 1)*0 =  + 0 + 1 chuyển các biểu thức chính quy thành các ô-tô-mát hữu hạn nhằm tạo ra
22
hàm xử lý chương trình nguồn thành các đơn vị từ vựng. Lex được cung
Lưu ý, các bước rút gọn sử dụng các tính chất đại số của biểu thức
chính quy (mục 3.1.3). cấp bởi hệ điều hành UNIX, trong khi Flex là sản phẩm của GNU.
( 2) Khi xây dựng các chương trình dịch, việc sử dụng các công cụ sinh bộ
Tiếp tục, chúng ta xây dựng các biểu thức r ij theo luật: phân tích từ vựng giúp cho lập trình viên xây dựng bộ phân tích cú pháp
( 2) (1) (1) (1) *
(1) nhanh hơn và dễ dàng hơn.
r =r +r (r ) r
ij ij i2 22 2j
Thay thế các (1) Ví dụ 3.6. Hình 3.11 mô tả một đoạn đầu vào của công cụ Lex/Flex,
r ij đã được xây dựng ở bước trên và rút gọn biểu thức nhằm mô tả các đơn vị từ vựng trong một ngôn ngữ lập trình.
chính quy, chúng ta có: [A-Za-z][A-Za-z0-9]*{
( 2) yylval.sIndex = *yytext - 'a';
r 11 =1 + 1 0( + 0 + 1)  = 1
* * * *
return ID;
( 2) }
r 12 = 1*0 + ( + 0 + 1)*( + 0 + 1) = 1*0(0 + 1)* [0-9]+ {
( 2) yylval.iValue = atoi(yytext);
r 21 =  + ( + 0 + 1) ( + 0 + 1)* = 
return NAT;
(2)
r 22 =  + 0 + 1 + ( + 0 + 1)(  + 0 + 1)*( + 0 + 1) = (0 + 1)* }
Biểu thức chính quy biểu diễn ngôn ngữ đoán nhận bởi OHD trong ">=" return GE;
( n) "<=" return LE;
"==" return EQ;
hình 3.10 là hợp của tất cả các r 1 j với j là trạng thái cuối, 2 là trạng thái "!=" return NE;
cuối duy nhất của OHD, do vậy, biểu thức chính quy cần xác định chỉ "while" return WHILE;
"if" return IF;
là r( n) = 1*0(0 + 1)*.
12
"else" return ELSE;
3.3 Ứng dụng của biểu thức chính quy Hình 3.11. Một đoạn đầu vào của công cụ Lex
Biểu thức chính quy thường được sử dụng để biểu diễn mẫu của xâu mà Dòng đầu tiên bên trái trong ví dụ trên chứa biểu thức chính quy mô tả một
chúng ta muốn tìm kiếm trong một văn bản. Trong mục này, chúng ta sẽ xem định danh trong ngôn ngữ lập trình, bắt đầu bởi một chữ cái và theo sau bởi
xét hai ứng dụng cơ bản của biểu thức chính quy: phân tích từ vựng và tìm không hay nhiều chữ cái hay chữ số. Các lệnh bên phải tương ứng dùng để
kiếm xâu. lưu trữ định danh đọc được (trong biến yytext) vào trong bảng các ký hiệu
(biến yylval), sau đó bộ phân tích từ vựng trả về hàng số ID , được chọn để
3.3.1 Công cụ sinh bộ phân tích từ vựng Lex/Flex biểu diễn các định danh. Dòng thứ hai bên trái mô tả các số nguyên dương,
Một trong những ứng dụng điển hình của biểu thức chính quy là đặc tả bộ gồm một dãy các chữ số và có ít nhất một chữ số. Các lệnh bên phải tương
phân tích từ vựng (lexical analyzer) của một chương trình dịch. Bộ phân ứng lưu trữ số đọc được vào bảng các ký hiệu và trả về hằng số NAT để
tích từ vựng đọc chương trình nguồn và nhận biết các đơn vị từ vựng, biểu diễn số nguyên dương. Các dòng tiếp theo xử lý các toán tử so sánh và
chẳng hạn như từ khóa, danh biểu, số, … các từ khóa.
Công cụ Lex/Flex đọc đầu vào là một danh sách các biểu thức chính
quy, mỗi biểu thức chính quy đi kèm với một đoạn mã nguồn yêu cầu bộ
phân tích từ vựng cần thực hiện khi tìm thấy một đơn vị từ vựng. Lex hay
Flex được gọi là công cụ sinh bộ phân tích từ vựng. Công cụ Lex/Flex

59 60
3.3.2 Tìm kiếm xâu với lệnh grep a. (b + )(ab)*(a + ).
Trong các hệ điều hành Unix/Linux, lệnh grep cho phép tìm kiếm các xâu b. (a + ba)*bb*.
ký tự trong các tệp văn bản. Các xâu ký tự cần tìm kiếm được mô tả bằng các c. (a + b + c + d)*(a + d).
biểu thức chính quy.
d. (01*)*0.
Cú pháp sử dụng lệnh grep có dạng:
Bài 3.3. Hãy chứng minh a + ab* = ab*.
grep pattern file-name
Bài 3.4. Hãy rút gọn các biểu thức chính quy sau:
trong đó, pattern là biểu thức chính quy mô tả xâu cần tìm kiếm và
file-name là tên tệp văn bản. a. (00)*0 + (00)*.

Một vài ví dụ sử dụng lệnh grep như sau: b. (0 + 1)( + 00)+ + (0 + 1).

grep “a*” file-name c. (0 + )0*1.

grep “[ab]*bb” file-name Bài 3.5. Hãy rút gọn biểu thức chính quy sau

grep “[a-z]*abc[a-z]*” file-name (0 + 1)*1(0 + 1) + (0 + 1)*1(0 + 1)(0 + 1).

grep “[a-z][0-9a-z]*” file-name Bài 3.6. Xây dựng OHKD tương ứng các biểu thức chính quy sau:

Lệnh grep thứ nhất tìm tất cả các xâu , a, aa, aaa, … trong tệp file- - (01)*(0 +10*)*
name. Lệnh grep thứ hai tìm tất cả các xâu trên bảng chữ {a, b} kết thúc - 10 + (0 + 01)1*0
bởi hai ký hiệu b đi liền nhau trong tệp file-name. Lệnh grep thứ ba
- (0 + 1)*(11+00) (0 + 1)*
tìm tất cả các xâu trên bảng chữ {a, b, …, z} chứa ít nhất một xâu con abc
trong tệp file-name. Lệnh grep cuối cùng tìm tất cả các xâu trên bảng Bài 3.7. Xây dựng OHD tương ứng các biểu thức chính quy sau:
chữ {a, b, …, z, 0, 1, …, 9} bắt đầu bởi một chữ cái trong tệp file- a. (0)*(1010)*
name.
b. (00 +11)*1*0*
3.4 Bài tập chương 3 Bài 3.8. Chuyển các OHD dưới đây thành các biểu thức chính quy
Bài 3.1. Xây dựng biểu thức chính quy cho các ngôn ngữ sau: tương ứng:
a. Tập hợp các xâu trên {a, b} chứa ít nhất xâu con aba. a.
 a b
b. Tập hợp các xâu trên {a, b} chứa nhiều nhất một cặp bb đi liền
→1 2 1
nhau.
2 3 1
c. Tập hợp các xâu trên {a, b, c} chứa ít nhất một ký hiệu a và ít *3 3 2
nhất một ký hiệu c.
b.
d. Tập hợp các xâu trên {0, 1} có tổng số các ký hiệu 0 và các ký  a b
hiệu 1 chia hết cho 5. →1 2 3
Bài 3.2. Hãy mô tả ngôn ngữ của các biểu thức chính quy sau: 2 1 3
*3 2 1

61 62
Bài 3.9. Sử dụng biểu thức chính quy mô tả số điện thoại cố định. Lưu
ý, mỗi số điện thoại có mã nước và mã tỉnh/thành phố.

Chương 4. Văn phạm chính quy và tính chất


của ngôn ngữ chính quy

Ngoài cách sử dụng ô-tô-mát hữu hạn và biểu thức chính quy để mô tả ngôn
ngữ chính quy, chúng ta còn có cách khác là văn phạm chính quy (regular
grammar).

4.1 Văn phạm chính quy


Văn phạm chính quy được định nghĩa thông qua văn phạm tuyến tính trái và
văn phạm tuyến tính phải.

4.1.1 Văn phạm tuyến tính phải và văn phạm tuyến tính
trái
Định nghĩa 4.1.
- Một văn phạm G = (N, , R, S) được gọi văn phạm tuyến tính
phải nếu tất cả các luật sinh có dạng:
A → wB, hoặc
A → w,
trong đó, A, B  N, w  *.
- Một văn phạm G = (N, , R, S) được gọi văn phạm tuyến tính
trái nếu tất cả các luật sinh có dạng:
A → Bw, hoặc A
→ w,
trong đó, A, B  N, w  *.
- Các văn phạm tuyến tính trái và văn phạm tuyến tính phải được
gọi là văn phạm chính quy.
Ví dụ 4.1. Cho các văn phạm sau:

63 64
G1 = ({S1}, {a, b}, R1, S1), o q → ap nếu (q, a) = p,
trong đó R1: S1 → bS1 | ab o qf →  nếu qf  F.
G2 = ({S2}, {a, b}, R2, S2), Bây giờ cần chứng minh rằng: một xâu được thừa nhận bởi M khi và
chỉ khi nó được sản sinh bởi G. Điều này là hiển nhiên khi chúng ta tiến
trong đó R2: S2 → S2ba | b
hành đồng thời quá trình dịch chuyển của M và quá trình sản sinh của G.
G1 là văn phạm tuyến tính phải và G2 là văn phạm tuyến tính trái. Như vậy,
Thật vây, xét w  L, tức là w được thừa nhận bởi M, giả sử
G1 và G2 là các văn phạm chính quy.
w = a1a2…an. Như thế, tồn tại các dịch chuyển để đoán nhận w trong M như
Ví dụ 4.2. Cho văn phạm G như sau: sau:
G = ({S}, {a, b}, R, S), (q0, a1) = q1, (q1, a2) = q2, …, (qn-1, an) = qf  F
trong đó R: S → aSb |  Theo cách xây dựng RG, trong G sẽ có các luật sinh tương ứng sau:
Văn phạm G không phải là văn phạm chính quy. q0 → a1q1, q1 → a2q2, …, qn-1 → anqf, qf → 

4.1.2 Ngôn ngữ chính quy và văn phạm chính quy Vậy trong G có dẫn xuất sau:

Không phải ngẫu nhiên mà chúng ta gọi các văn phạm tuyến tính trái và q0 ⇒ a1q1 ⇒ a1a2q2 ⇒ … ⇒ a1a2…anqf ⇒ a1a2…an
văn phạm tuyến tính phải là văn phạm chính quy. Thực tế, ngôn ngữ sản Như thế, w = a1a2…an thuộc L(G), nghĩa là L = L(G).
sinh bởi văn phạm chính quy là ngôn ngữ chính quy.
Điều kiện đủ: Nếu một ngôn ngữ được sản sinh bởi văn phạm chính quy
Định lý 4.1. Một ngôn ngữ là chính quy khi và chỉ khi ngôn ngữ đó thì đó là ngôn ngữ chính quy.
được sản sinh bởi một văn phạm chính quy.
Chúng ta sẽ chứng minh rằng: ngôn ngữ được sinh ra bởi văn phạm
Chứng minh: chính quy thì được thừa nhận bởi ô-tô-mát hữu hạn không đơn định.
Điều kiện cần: Nếu L là ngôn ngữ chính quy thì tồn tại văn phạm chính quy Giả sử G = (NG, G, RG, SG) là văn phạm chính quy sản sinh ra ngôn
G sản sinh L. ngữ L. Chúng ta xây dựng OHKD M = (Q, , , q0, F) thừa nhận L từ G
Bởi vì L là ngôn ngữ chính quy, nên theo định nghĩa ngôn ngữ chính như sau:
quy, thì tồn tại ô-tô-mát hữu hạn không đơn định M đoán nhận L, nghĩa là L - Với mỗi Ni  NG thì đặt Ni vào Q.
= L(M), trong đó:
-  = G.
M = (Q, , , q0, F)
- SG là biến đầu trong G thì trạng thái đầu trong Q là q0 = SG.
Chúng ta sẽ xây dựng văn phạm chính quy G = (NG, G, RG, SG) từ
- Nếu Ni → a1a2…anNj thuộc RG thì đặt vào  các dịch chuyển
OHKD M sao cho L = L(G). Các phần tử của G được xây dựng như sau:
trạng thái và đồng thời thêm vào Q các trạng thái mới sao cho:
- G = , bảng chữ của M là tập các ký tự kết thúc trong văn
phạm G. *(Ni, a1a2…an) = Nj

- NG = Q, mỗi trạng thái của M trở thành một biến trong G. Điều này được minh họa bởi hình vẽ dưới đây:

- SG = q0, trạng thái đầu của M là biến đầu của G. a1 a2 an


N Nj
- RG được xây dựng như sau:

65 66
Hình 4.1. Minh họa dịch chuyển *(Ni, a1a2…an) = Nj Chúng ta xây dựng văn phạm chính quy G = ({q0, q1, q2}, {a, b}, R,
- Nếu Ni → a1a2…an thuộc RG thì thêm vào Q và F trạng thái kết q0), trong đó R được xây dựng như sau:
thúc Nf, đặt vào  các dịch chuyển trạng thái và đồng thời thêm q0 → aq1
vào Q các trạng thái mới sao cho: q0 → aq2
*(Ni, a1a2…an) = Nf
q0 → bq2
Điều này được minh họa bởi hình vẽ dưới đây:
q1 → aq0
a1 a2 an q1 → bq1
N Nf
q2 → aq2
Hình vẽ 4.2. Minh họa dịch chuyển *(Ni, a1a2…an) = Nf
Như vậy, chúng đã tìm hiểu các cách khác nhau để biểu diễn lớp ngôn
Việc chứng minh xâu w được sinh bởi G thì cũng được thừa nhận bởi M
ngữ chính quy: ô-tô-mát hữu hạn, biểu thức chính quy và văn phạm chính
tương tự như chứng minh điều kiện cần.
quy. Chúng ta cũng đã chỉ ra rằng các cách biểu diễn khác nhau này là
Lưu ý rằng chúng ta cũng có thể xây dựng được OHKD từ một văn tương đương nhau.
phạm tuyến tính trái tương tự như trên.
4.2 Các tính chất đóng của ngôn ngữ chính quy
Ví dụ 4.3. Xây dựng ô-tô-mát hữu hạn không đơn định thừa nhận ngôn
ngữ sinh ra bởi văn phạm sau: Trong mục này, chúng ta sẽ chứng minh các định lý có dạng “nếu một
ngôn ngữ L được xây dựng từ một vài ngôn ngữ chính quy bởi các phép
S → aaS | aA
toán, chẳng hạn như phép hợp, phép giao… thì L cũng là ngôn ngữ chính
A → abcA | c quy”. Các định lý này được gọi là các tính chất đóng của ngôn ngữ chính
OHKD được xây dựng trong hình 4.3. quy, vì chúng chỉ ra rằng lớp các ngôn ngữ chính quy là đóng dưới các
phép toán đó.
a a b
S A 4.2.1 Tính đóng của ngôn ngữ chính quy dưới các phép
toán tập hợp
a a c
c Tính đóng dưới phép hợp
Định lý 4.2. Nếu L1 và L2 là các ngôn ngữ chính quy thì L1  L2 cũng là
ngôn ngữ chính quy.
Hình vẽ 4.3. OHKD cho ví dụ 3.6 Chứng minh: Thật vậy, vì L1 và L2 là các ngôn ngữ chính quy, nên tồn tại
Ví dụ 4.4. Xây dựng văn phạm chính quy từ ô-tô-mát hữu hạn trong các biểu thức chính quy r1 và r2 sao cho L1 = L(r1) và L2 = L(r2). Theo định
bảng dịch chuyển sau: nghĩa của biểu thức chính quy, r1 + r2 cũng là biểu thức chính quy biểu
 a b diễn ngôn ngữ L(r1)  L(r2). Vậy L1  L2 là ngôn ngữ chính quy. Tính đóng
→ q0 {q1, q2} {q2} dưới phép bù
q1 {q0} { q1} Định lý 4.3. Nếu L là ngôn ngữ chính quy trên bảng chữ , thì
* q2 {q2}  *
L =  − L cũng là ngôn ngữ chính quy.

67 68
Chứng minh: Cho OHD M = (Q, , , q0, F) thừa nhận L, thì L được nhận xâu vào khi đồng thời cả hai OHD M1 và M2 cùng đoán nhận xâu
thừa nhận bởi OHD M’ = (Q, , , q0, Q − F). Nghĩa là, M’ hoàn toàn như M, vào. Như vậy, M được xây dựng như sau:
nhưng các trạng thái không chấp nhận trong M trở thành các trạng thái chấp M = (Q1 x Q2, 1  2, , (q01, q02), F1 x F2)
nhận trong M’ và ngược lại. Như thế, w thuộc L(M’) khi và chỉ khi *(q0, w)
 Q − F, mà điều này chỉ đúng khi w không thuộc L(M). Lưu ý, điều này chỉ trong đó, ((p, q), a) = (1(p, a), 2(q, a)), với p  Q1, q  Q2,
đúng khi M là OHD. a  1  2.

Ví dụ 4.5. Cho L là ngôn ngữ gồm các xâu trên bảng chữ  = {0, 1} kết Dễ dàng nhận thấy rằng L(M) = L(M1)  L(M2).
thúc bởi 0. Hình 4.4 (a) mô tả OHD thừa nhận L. Ngôn ngữ bù của L gồm Thật vậy, *((q01, q02), w) = (1*(q01, w), 2*(q02, w)), như thế M chỉ
các xâu trên  không kết thúc bởi 0, nghĩa là kết thúc bởi 1. OHD thừa chấp nhận w khi 1*(q01, w)  F1 và 2*(q02, w)  F2, nghĩa là M chỉ chấp
nhận L = { 0, 1 } * − L trong hình 4.4 (b). nhận w khi M1 chấp nhận w và M2 chấp nhận w. Vậy, M chấp nhận
L(M1)  L(M2).
0 0
1 0 1 0 Ví dụ 4.6. Cho L1 là ngôn ngữ chính quy có chứa ít nhất một ký hiệu 0
q0 q1 được thừa nhận bởi OHD M1 (hình 4.5 (a)) và L2 là ngôn ngữ chính quy có
1 q0 q1
1 chứa ít nhất một ký hiệu 1 được thừa nhận bởi OHD M2 (hình 4.5 (b)).
a) b) 1 0, 1
0
Hình 4.4. OHD cho ví dụ 4.5 q0 q1

Tính đóng dưới phép giao a)


Định lý 4.4. Nếu L1 và L2 là các ngôn ngữ chính quy thì L1  L2 cũng
là ngôn ngữ chính quy. 0 0, 1
1
Chứng minh: Chúng ta có thể chứng minh bằng hai cách. p0 p1

Cách 1: Các phép toán hợp, bù và giao trên tập hợp thực ra có mối b)
quan hệ chặt chẽ với nhau. Thật vậy, ta có:
Hình vẽ 4.5. Hai OHD cho ví dụ 4.6
L 1 L 2 = L 1 L 2 OHD M thừa nhận ngôn ngữ giao của L1 và L2 được mô tả trong
Vậy áp dụng các định lý 4.2 và 4.3, chúng ta có thể kết luận rằng L1 hình 4.6. Chúng ta dễ dàng nhận thấy rằng, OHD M thừa nhận ngôn ngữ gồm
 L2 cũng là ngôn ngữ chính quy. ít nhất một ký hiệu 0 và ít nhất một ký hiệu 1.

Cách 2: Chúng ta xây dựng trực tiếp OHD thừa nhận ngôn ngữ L1  L2 1
1
từ các OHD thừa nhận L1 và L2. Giả sử M1 = (Q1, 1, 1, q01, F1) và q0, p0 q0, p1
M2 = (Q2, 2, 2, q02, F2) là các OHD thừa nhận tương ứng L1 và L2.
Chúng ta sẽ xây dựng OHD M bắt chước thực hiện đồng thời M1 và M2.
Mỗi trạng thái của M sẽ là một cặp trạng thái: một trạng thái của M1 và
0 0
một trạng thái của M2. Bảng chữ của M sẽ là hợp của các bảng chữ của M1
và M2. Một dịch chuyển trong M được xây dựng tương ứng một dịch 0
chuyển đồng thời trên M1 và M2 khi đọc cùng một ký hiệu. M sẽ đoán 1 0, 1
q1, p0 q1, p1
69 70
Hình vẽ 4.6. Xây dựng OHD giao của hai OHD Như thế, M’ = (Q’, ’, ’, q0’, F’) có các thành phần như sau:
Tính đóng dưới phép hiệu - Q’ = Q  {q0’}
Định lý 4.5. Nếu L1 và L2 là các ngôn ngữ chính quy thì L1 − L2 cũng - ’ = 
là ngôn ngữ chính quy.
- F’ = {q0}
Chứng minh: Chúng ta nhận thấy rằng L − L = L  L . Mà bù của
1 2 1 2
- ’ được xây dựng như sau:
L2 là ngôn ngữ chính quy, L  L là ngôn ngữ chính quy. Vậy L1 − L2
1 2
 nếu (q, a) = p thì thêm vào ’(p, a) = q
cũng là ngôn ngữ chính quy.
 qf  F thêm vào (q0’, ) = qf.
4.2.2 Tính đóng dưới các phép toán khác
Với cách xây dựng M’ như trên, chúng ta dễ dàng nhận thấy rằng với mọi
Tính đóng dưới phép ghép nối và phép bao đóng xâu w được đoán nhận bởi M, thì xâu wR sẽ được đoán nhận bởi M’.
Định lý 4.6. Nếu L1 và L2 là các ngôn ngữ chính quy thì L1L2 cũng là Ví dụ 4.7. Cho L là ngôn ngữ gồm các xâu kết thúc bởi xâu con ab trên
ngôn ngữ chính quy.  = {a, b}, xây dựng OHKD đoán nhận ngôn ngữ LR.
Chứng minh: Tương tự như chứng minh cho phép hợp. Thật vậy, vì L1 Trước hết, chúng ta xây dựng OHKD đoán nhận L trong hình 4.7 (a). Sau
và L2 là các ngôn ngữ chính quy, nên tồn tại các biểu thức chính quy r1 và đó, chúng ta xây dựng OHKD đoán nhận LR trong hình 4.7 (b).
r2 sao cho L1 = L(r1) và L2 = L(r2). Theo định nghĩa của biểu thức chính
quy, r1r2 cũng là biểu thức chính quy biểu diễn ngôn ngữ L(r1)L(r2). Vậy a, b a b
L1L2 là ngôn ngữ chính quy. q0 q1 q2
*
Định lý 4.7. Nếu L là các ngôn ngữ chính quy thì L cũng là ngôn ngữ a)
chính quy.
Chứng minh: Tương tự như trên, sử dụng định nghĩa của biểu thức a, b a b 
chính quy. q0 q1 q2 q0’

Tính đóng dưới phép nghịch đảo b)


R
Định lý 4.8. Nếu L là các ngôn ngữ chính quy thì L cũng là ngôn ngữ Hình 4.7. Xây dựng OHKD đoán nhận ngôn ngữ nghịch đảo
chính quy. Ví dụ 4.8. Chúng ta định nghĩa phép chia của hai ngôn ngữ L1 và L2
Chứng minh: Chúng ta chứng minh bằng cách xây OHKD thừa nhận LR như sau:
từ OHKD thừa nhận L. Giả sử OHKD M = (Q, , , q0, F) thừa nhận L1/L2 = {u | (v  L2), uv  L1}.
L1, chúng ta xây dựng M’ = (Q’, ’, ’, q0’, F’) thừa nhận LR với ý tưởng
Chẳng hạn, L1 = {a, abb, baa}, L2 = {a}. Khi đó, L1/L2 = {, ba}.
như sau:
Hãy chứng minh rằng với L2 là ngôn ngữ bất kỳ, L1 là ngôn ngữ chính
1. Đảo ngược tất cả các cung trong biểu đồ dịch chuyển của M.
quy thì L1/L2 là ngôn ngữ chính quy.
2. Trạng thái đầu trong M trở thành trạng thái cuối duy nhất
Thật vậy, giả sử L1 được thừa nhận bởi OHD M = (Q, , , q0, F). Với
trong M’.
bất kỳ xâu u  L1/L2, thì tồn tại xâu v  L2 sao cho uv  L1, nghĩa là
3. Thêm vào M’ một trạng thái đầu mới q0’ và các dịch chuyển- (q0, uv) = ((q0, u), v)  F. Nói cách khác, giả sử khi M đoán nhận u,
đến tất cả các trạng thái cuối của M. M đạt đến trạng thái qi = (q0, u). Nếu tồn tại xâu v  L2 sao cho

71 72
(qi, v)  F, thì u nên được thừa nhận bởi ô-tô-mát M’ cho L1/L2. Nghĩa là, Để xác định xem L có chứa mọi xâu hay không thì chỉ cần chúng ta xác
qi nên được xem là trạng thái cuối của M’. Như thế, chúng ta định nghĩa định xem ngôn ngữ bù của L có là rỗng không. Để thực hiện điều này,
chúng ta xây dựng ô-tô-mát đoán nhận ngôn ngữ bù của L và kiểm tra ô-
F’ = {q  Q | v  L2, (q, v)  F}, tô-mát này không đoán nhận một xâu nào.
và M’ = (Q, , , q0, F’). Rỏ ràng M’ đoán nhận L1/L2.
Bài toán 4. Xác định xem một ngôn ngữ chính quy L1 có là tập con của
4.3 Các thuật toán liên quan đến ngôn ngữ chính ngôn ngữ chính quy L2 khác?
quy Để xác định L1  L2, chỉ cần kiểm tra L  L = ? Để thực hiện điều
1 2
Trong mục này, chúng ta sẽ quan tâm đến làm thế nào để giải quyết các này, chúng ta sử dụng các tính chất đóng của ngôn ngữ chính quy và thuật
bài toán liên quan đến ngôn ngữ chính quy. Chúng ta đã biết, một ngôn ngữ toán xác định ngôn ngữ rỗng trong bài toán 1.
thông thường là vô hạn, nên không thể biểu diễn ngôn ngữ bằng cách liệt kê Bài toán 5. Cho L1 và L2 là các ngôn ngữ chính quy, xác định xem L1
tất cả các xâu thuộc ngôn ngữ. Tuy nhiên, chúng ta sử dụng một trong bốn = L2?
cách biểu diễn ngôn ngữ chính quy đã biết. Trong các phần trước, chúng
ta cũng đã chỉ ra rằng có thể chuyển đổi giữa bốn cách biểu diễn đối với một Chúng ta có thể sử dụng kết quả của bài toán 4 để giải quyết bài toán này.
ngôn ngữ chính quy. Chúng ta sẽ xem xét một vài bài toán cơ bản về ngôn Thật vậy, L1 = L2 khi và chỉ khi L1  L2 và L2  L1.
ngữ như:
4.4 Sự tương đương và cực tiểu hóa các ô-tô-mát
a. Một ngôn ngữ có là rỗng không?
Trong mục này, chúng ta sẽ trả lời câu hỏi hai OHD khác nhau có biểu
b. Một xâu w có thuộc ngôn ngữ L không? diễn cùng một ngôn ngữ chính quy không? Khi hai OHD biểu diễn cùng
c. Một ngôn ngữ L có phải là *? một ngôn ngữ, thì ta nói hai OHD là tương đương. Từ vấn đề này, chúng ta
sẽ tìm cách cựu tiểu hóa OHD: tức là xây dựng OHD có tối thiểu số trạng
d. Một ngôn ngữ có là tập con của ngôn ngữ khác? thái tương đương với một OHD cho trước.
e. Hai ngôn ngữ có “bằng nhau” không?
4.4.1 Sự tương đương của các trạng thái
Bài toán 1. Xác định xem ngôn ngữ chính quy L có là rỗng không?
Mục đích của chúng ta là xác định xem hai trạng thái khác nhau p và q
Bài toán này có thể được giải quyết bởi một thủ tục hiệu quả. Thật vậy, L trong một OHD có thể được thay thế bởi một trạng thái duy nhất mà có
có thể được biểu diễn bằng một ô-tô-mát hữu hạn (đơn định hoặc không đơn chức năng như p và q.
định). Nếu tồn tại một đường đi từ trạng thái đầu đến một trong các trạng
thái cuối thì L là khác rỗng, ngược lại thì L là rỗng. Chúng ta nói rằng, hai trạng thái p và q là tương đương nếu:

Bài toán 2. Xác định xem xâu w có thuộc ngôn ngữ chính quy L - Với mọi xâu w, *(p, w) cho kết quả là trạng thái kết thúc và
không? *(q, w) cho kết quả cũng là trạng thái kết thúc hoặc *(p, w)
cho kết quả là trạng thái không kết thúc và *(q, w) cho kết quả
Bài toán này có thể được giải quyết bởi một thủ tục hiệu quả. Thật vậy, cũng là trạng thái không kết thúc.
xây dựng một ô-tô-mát hữu hạn đơn định mô tả L, sau đó thực hiện quá
trình đoán nhận w. Nếu sau khi đọc xong w ô-tô-mát đạt đến một trong các Lưu ý, chúng ta không yêu cầu *(p, w) và *(q, w) cho cùng trạng thái mà
trạng thái cuối thì w thuộc L, ngược lại thì w không thuộc L. chỉ cho kết quả cùng trạng thái kết thúc hoặc không kết thúc.

Bài toán 3. Xác định xem ngôn ngữ L chính quy có phải là *? Ngược lại, hai trạng thái không tương đương được gọi là phân biệt.
Nghĩa là, trạng thái p phân biệt với trạng thái q, nếu tồn tại ít nhất một xâu

73 74
w sao cho một trong hai dịch chuyển *(p, w) và *(q, w) cho trạng thái kết Trước hết, các cặp trạng thái gồm có một thái kết thúc và một trạng thái
thúc và dịch chuyển còn lại cho trạng thái không kết thúc. không kết thúc được đánh dấu. Thực hiện bước 2 của thuật toán, chúng ta
không tìm thấy thêm cặp trạng thái phân biệt nào nữa.
Ví dụ 4.9. Cho OHD trong hình dưới đây.
0 B X
B E 0, 1
0 1 C X
0, 1 0, 1
D X X
A D G
0 E X X
1 0
C F F X X X
1
1 G X X X
Hình 4.8. OHD cho ví dụ 4.9 A B C D E F
Chúng ta có thể dễ dàng xác định được một số cặp trạng thái không Hình 4.9. Bảng đánh dấu các cặp trạng thái phân biệt cho ví dụ 4.10
tương đương hay phân biệt. Chẳng hạn, A và B là cặp trạng thái phân biệt. Như thế, chúng ta có các cặp trạng thái tương đương sau: {A, C},
Bởi vì, A là trạng thái không kết thúc, trong khi B là trạng thái kết thúc.
{A, F}, {C, F}, {B, D}, {B, E}, {B, G}, {D, E}, {D, G}.
Nghĩa là, xâu rỗng phân biệt hai trạng thái này, *(B, ) đoán nhận trong khi
*(A, ) không đoán nhận. Định lý 4.9. Nếu hai trạng thái không được phân biệt bởi thuật toán xây
Để xác định sự tương đương của các trạng thái, chúng ta sử dụng chúng ta dựng bảng đánh dấu thì hai trạng thái đó tương đương.
sử dụng thuật toán xây dựng bảng đánh dấu như sau: Chứng minh: Chúng ta sẽ chứng minh bằng phương pháp phản chứng.
Giả sử rằng định lý sai, nghĩa là, có ít nhất một cặp trạng thái {p, q} sao
1. Nếu p là trạng thái không kết thúc và q là trạng thái kết thúc thì
cho:
{p, q} là cặp trạng thái phân biệt.
1. Hai trạng thái p và q là phân biệt, nghĩa là tồn tại xâu w sao cho chỉ
2. Cho p và q là các trạng thái sao cho với ký hiệu vào a, r = (p, a)
có đúng một trong hai dịch chuyển *(p, w) và *(q, w) cho kết quả
và s = (q, a) là cặp trạng thái phân biệt. Khi đó {p, q} cũng là
là trạng thái kết thúc.
cặp trạng thái phân biệt. Thật vậy, bởi vì {r, s} là cặp trạng thái
phân biệt, nên tồn tại xâu w phân biệt r và s, nghĩa là chỉ một 2. Thuật toán xây dựng bảng đánh dấu không xác định được p và q là
trong hai dịch chuyển *(r, w) và *(s, w) cho kết quả là trạng thái phân biệt.
kết thúc, còn một dịch chuyển cho kết quả là trạng thái không kết Gọi cặp trạng thái như thế là cặp trạng thái xấu.
thúc. Khi đó, *(p, aw) và *(q, aw) cho cùng kết quả với *(r, w)
và *(s, w), nghĩa là {p, q} cũng là cặp trạng thái phân biệt bởi Nếu có các cặp trạng thái xấu, thì phải có một số cặp trong số đó được
xâu aw. phân biệt bởi các xâu ngắn nhất trong số tất cả các xâu phân biệt các cặp
trạng thái xấu. Giả sử p và q là một cặp như thế, và xâu w = a1a2…an là xâu
Ví dụ 4.10. Xây dựng bảng đánh dấu cho OHD trong hình 4.8. ngắn nhất trong số các xâu phân biệt p và q. Như thế, chỉ có một trong dịch
Trong bảng đánh dấu (hình 4.9), các cặp trạng thái phân biệt được đánh chuyển *(p, w) và *(q, w) cho kết quả là trạng thái kết thúc.
dấu X, các cặp trạng thái tương đương được để trống, các ô bôi đen không Chúng ta có nhận xét rằng, w không thể là xâu rỗng, bởi vì nếu xâu
được sử dụng. Ban đầu, không có cặp nào bị đánh dấu. Chúng ta thực hiện rỗng phân biệt một cặp trạng thái thì cặp trạng thái đó phải được đánh dấu bởi
việc đánh dấu theo thuật toán xây dựng bảng đánh dấu đã trình bày ở trên. bước 1 của thuật toán xây dựng bảng đánh dấu. Như vậy, n ≥ 1.
75 76
Xét các trạng thái r = (p, a1) và s = (q, a1). Hai trạng thái r và s được 0 1 0
phân biệt bởi xâu a2a3…an, vì *(r, a2a3…an) và *(s, a2a3…an) cho cùng 0
1 C D
kết quả với *(p, w) và *(q, w). Tuy nhiên, xâu a2a3…an ngắn hơn bất kỳ A B
xâu nào phân biệt cặp trạng thái xấu (theo cách chọn cặp trạng 1 1
thái p và q). Như thế, r và s không phải là cặp trạng thái xấu. Hay nói cách 1
0
khác, thuật toán xây dựng bảng đánh dấu phải xác định được r và s là cặp 0 E
trạng thái phân biệt.
Khi xác định được r và s là cặp trạng thái phân biệt, bước 2 của thuật a) b)
toán sẽ xác định được p và q là cặp trạng thái phân biệt, bởi vì nó xác định
được r = (p, a1) phân biệt với s = (q, a1). Như vậy, mâu thuẫn với giả Hình 4.10. Hai OHD tương đương
thiết thuật toán không xác định được p và q là phân biệt. Vậy chúng ta kết B X
luận: nếu không tồn tại các cặp trạng thái xấu, bất kỳ cặp trạng thái phân
C X
biệt nào cũng phải được xác định (hay đánh dấu) bởi thuật toán xây dựng
bảng đánh dấu, và như vậy định lý đúng. D X
E X X X
4.4.2 Sự tương đương của các OHD
Từ bảng đánh dấu sự tương đương các trạng thái, chúng ta dễ dàng xác A B C D
định được sự tương đương của hai OHD. Thật vậy, giả sử có hai OHD M1 Hình 4.11. Bảng đánh dấu các cặp trạng thái phân biệt cho ví dụ 4.11
và M2. Xét OHD M3 mới là hợp của hai OHD M1 và M2. Khi đó, OHD M3 có
A và C là cặp trạng thái tương đương, vậy hai OHD là tương đương, tức là
hai trạng thái đầu. Áp dụng thuật toán xây dựng bảng đánh dấu, nếu hai OHD
chúng cùng thừa nhận một ngôn ngữ. Thật vậy, hai OHD này thừa nhận ngôn
M1 và M2 là tương đương thì cặp trạng thái đầu phải là cặp trạng thái tương
ngữ gồm xâu rỗng và các xâu kết thúc bởi 0 trên bảng chữ {0, 1}.
đương. Ngược lại, nếu cặp trạng thái đầu là cặp trạng thái phân biệt thì M1 và
M2 không tương đương. 4.4.3 Cực tiểu hóa OHD
Ví dụ 4.11. Xét hai OHD trong hình 3.13. Hai OHD này cùng đoán Cực tiểu hóa một OHD nghĩa là tìm một OHD tương đương có số trạng
nhận ngôn ngữ gồm các xâu trên bảng chữ {0, 1} kết thúc bởi ký hiệu 0. thái ít nhất. OHD có số trạng thái ít nhất là duy nhất đối với một ngôn ngữ.
Chúng ta coi hai OHD như là một OHD với các trạng thái là A, B, C, D và OHD như thế được gọi đơn giản là OHD nhỏ nhất. Ý tưởng của việc xây
E. Bây giờ xây dựng bảng đánh dấu các trạng thái phân biệt (hình vẽ 3.14) dựng OHD nhỏ nhất là:
của OHD này.
1. Trước hết, loại bỏ các trạng thái không đạt đến được từ trạng thái
đầu.
2. Sau đó, chia các trạng thái thành các nhóm, sao cho các trạng thái
trong cùng một nhóm là tương đương nhau và không có cặp trạng
thái nào trong các nhóm khác nhau là tương đương nhau.
Để thực hiện công việc này, trước hết chúng ta xem xét định lý sau.

77 78
Định lý 4.10. (Tính chất bắc cầu) Cho OHD, nếu các trạng thái p và q a là một ký hiệu vào. Thế thì phải tồn tại nhóm các trạng thái T, sao
là tương đương và các trạng thái q và r là tương đương thì các trạng thái p và cho với mọi trạng thái q trong S, (q, a) cho kết quả là trạng thái
r cũng tương đương. thuộc T. Nếu không, giả sử có hai trạng thái r và s trong S mà
Chứng minh: Chứng minh bằng phản chứng. Giả sử {p, q} và {q, r} là (r, a) và (s, a) cho hai trạng thái trong hai nhóm khác nhau, khi
các cặp trạng thái tương đương, còn {p, r} là cặp trạng thái không tương đó theo định lý 4.11 hai trạng thái r và s là phân biệt. Điều này là
đương. Thế thì tồn tại ít nhất một xâu w sao cho chỉ có một trong hai dịch mâu thuẫn với giả thiết. Vậy min(S, a) = T.
chuyển *(p, w) và *(r, w) là cho trạng thái kết thúc. Không mất tính tổng 4. Trạng thái đầu của Mmin là nhóm có chứa trạng thái đầu của M.
quát giả sử *(p, w) cho trạng thái kết thúc và *(r, w) cho trạng thái không
5. Tập hợp các trạng thái cuối của Mmin là tập hợp các nhóm có chứa
kết thúc. Xét kết quả của dịch chuyển *(q, w). Nếu *(q, w) cho trạng thái
trạng thái cuối của M. Lưu ý rằng, nếu một nhóm có chứa một trạng
kết thúc, thì {p, q} là tương đương, nhưng {q, r} là không tương đương.
thái kết thúc, thì tất cả các trạng thái còn lại của nhóm đều là trạng
Nếu *(q, w) cho trạng thái không kết thúc, thì {q, r} là tương đương,
thái kết thúc. Bởi vì, một trạng thái kết thúc và một trạng thái không
nhưng {p, q} là không tương đương. Vậy ta kết luận rằng {p, r} phải là
kết thúc bao giờ cũng phân biệt nhau, nên chúng không thể ở trong
cặp trạng thái tương đương.
cùng một nhóm tương đương.
Chúng ta có thể sử dụng định lý 4.10 để chia tập các trạng thái của một
Ví dụ 4.12. Quay trở lại ví dụ 3.10, ta xây dựng OHD nhỏ nhất trong
OHD thành các nhóm tương đương. Chúng ta xem xét định lý 4.11.
hình 4.12. Chúng ta có các cặp trạng thái tương đương là: {A, C}, {A, F},
Định lý 4.11. Khi chia tập các trạng thái của một OHD thành các {C, F}, {B, D}, {B, E}, {B, G}, {D, E} và {D, G}. Vậy các nhóm trạng thái
nhóm, sao cho các trạng thái trong cùng một nhóm là tương đương nhau thì tương đương là: {A, C, F} và {B, D, E, G}.
sẽ không có cặp trạng thái nào trong hai nhóm khác nhau là tương đương
nhau. 1 0, 1
Chứng minh: Thật vậy, giả sử có hai nhóm S và T khác nhau, p trong 0
ACF BDEG
nhóm S là tương đương với q trong nhóm T. Khi đó, theo định lý 4.10
(tính chất bắc cầu) các trạng thái trong nhóm S sẽ tương đương với các Hình 4.12. OHD nhỏ nhất tương đương OHD trong hình 4.8
trạng thái trong nhóm T. Vậy thì theo cách chia S và T chỉ là một nhóm.
Ví dụ 4.13. Xây dựng OHD nhỏ nhất tương đương với OHD trong
Điều này mâu thuẫn với giả thiết.
hình 4.13.
Từ định lý 4.11, chúng ta nhận thấy rằng mỗi trạng thái chỉ thuộc một
1 0
nhóm tương đương. q1 q3 q5 0,1
Bây giờ, chúng ta có thể đưa ra thuật toán cụ thể để xác định OHD nhỏ 1
nhất của một OHD M = (Q, , , q0, F) như sau: 0 0 1
1. Sử dụng thuật toán xây dựng bảng đánh dấu để xác định tất cả các 0
cặp trạng thái tương đương. 1 1
q0 q2 q4 0
2. Chia tập trạng thái Q vào trong các nhóm tương đương, sao cho các
trạng thái trong cùng một nhóm là tương đương nhau.
Hình 4.13. OHD cho ví dụ 4.13
3. Xây dựng OHD nhỏ nhất Mmin bởi việc sử dụng các nhóm trạng thái
như là các trạng thái của nó. Giả sử min là hàm dịch chuyển Trước hết, chúng ta sử dụng thuật toán xây dựng bảng đánh dấu để xác
của Mmin. Giả sử S là một nhóm các trạng thái tương đương của M, định tất cả các cặp trạng thái tương đương (hình 4.14).

79 80
q1 4.5 Nhận biết các ngôn ngữ không chính quy
Chúng ta đã xem xét bốn cách khác nhau để mô tả các ngôn ngữ chính
q2 X X
quy:
q3 X X
- Ô-tô-mát hữu hạn đơn định,
q4 X X X X
- Ô-tô-mát hữu hạn không đơn định,
q5 X X X X X
- Biểu thức chính quy,
q0 q1 q2 q3 q4
- Văn phạm chính quy.
Hình 4.14. Bảng đánh dấu các cặp trạng thái phân biệt cho ví dụ 4.11
Như thế, để chỉ ra một ngôn ngữ là chính quy, chúng ta chỉ cần chứng tỏ
Bước 1 của thuật toán xây dựng bảng đánh dấu cho phép xác định các cặp rằng tồn tại ít nhất một trong bốn cách trên biểu diễn ngôn ngữ đó. Trong
trạng thái phân biệt: {q0, q2}, {q0, q3}, {q0, q5}, {q1, q2}, {q1, q3}, {q1, q5}, mục này chúng ta sẽ trình bày một kỹ thuật, được gọi là định lý bơm, để
{q2, q4}, {q3, q4}, {q4, q5}. chứng minh rằng một ngôn ngữ không là chính quy.
Bước 2 của thuật toán xác định thêm các cặp trạng thái phân biệt:
4.5.1 Định lý bơm cho ngôn ngữ chính quy
- {q2, q5}, vì (q2, 1) = q4 và (q5, 1) = q5, {q4, q5} đã là cặp trạng
Định lý này cho phép chúng ta nhận biết các ngôn ngữ không chính
thái phân biệt.
quy. Định lý được xây dựng dựa trên ý tưởng dưới đây.
- {q3, q5}, vì (q3, 1) = q4 và (q5, 1) = q5, {q4, q5} đã là cặp trạng
Các ngôn ngữ chính quy có thể vô hạn, tuy nhiên các ô-tô-mát biểu
thái phân biệt.
diễn ngôn ngữ chính quy có số hữu hạn các trạng thái, giả sử là m (m > 0).
- {q0, q4}, vì (q0, 1) = q2 và (q4, 1) = q5, {q2, q5} đã là cặp trạng Như thế, với mọi xâu có độ dài lớn hơn m, việc thực hiện ô-tô-mát trên
thái phân biệt. xâu này phải vượt qua cùng một trạng thái qi nào đó ít nhất hai lần với một
- {q1, q4}, vì (q1, 0) = q0 và (q4, 0) = q4, {q0, q4} đã là cặp trạng phần khác rỗng của xâu ngăn cách giữa hai nhịp vượt này (hình 4.16).
thái phân biệt. x u y
q0 qi qi
Dựa vào bảng đánh dấu, chúng ta xác định được hai cặp trạng thái qf
tương đương: {q0, q1} và {q2, q3}. OHD nhỏ nhất có các trạng thái sau: {q0, Hình 4.16. Minh họa ý tưởng định lý bơm
q1}, {q2, q3}, {q4} và {q5}. Trong đó, {q0, q1} là trạng thái đầu và {q2, Từ đó, với ký hiệu các xâu như trên hình 4.16, thì mọi xâu có dạng xu*y
q3}, {q5} là các trạng thái cuối. Cuối cùng, chúng ta xây dựng được OHD cũng được thừa nhận bởi ô-tô-mát và thuộc ngôn ngữ. Dưới đây, chúng ta sẽ
nhỏ nhất trong hình 4.15. phát biểu và chứng minh một cách hình thức định lý bơm.
q5 0,1
Định lý 4.12. (Định lý bơm cho ngôn ngữ chính quy) Cho L là ngôn ngữ
chính quy vô hạn. Như thế, tồn tại một số nguyên dương m sao cho mọi xâu
0 1 w thuộc L mà |w|  m, xâu w có thể được phân tích thành ba xâu, w = xuy, sao
0
cho:
1 1
q0, q1 q2, q3 q4 0 1. u  
Hình 4.15. OHD nhỏ nhất của ví dụ 4.13 2. |xu|  m

81 82
3. k  0, xuky  L 4.5.2 Ứng dụng định lý bơm
Nghĩa là, chúng ta luôn tìm được xâu u khác rỗng, mà xâu này có thể Chúng sẽ xét một số ví dụ sử dụng định lý bơm để chứng minh một
được “bơm”, tức là xâu u có thể được lặp nhiều lần hoặc xóa nó (khi k = ngôn ngữ không chính quy. Để chứng minh một ngôn ngữ không chính
0) mà xâu kết quả xuky luôn thuộc L. quy, chúng ta sẽ sử dụng phương pháp phản chứng: bằng cách giả sử ngôn
ngữ đó là chính quy, vậy ngôn ngữ đó phải thỏa mãn định lý bơm, nếu
Chứng minh: Giả sử L là ngôn ngữ chính quy. Như thế tồn tại OHD M =
không thì ta kết luận ngôn ngữ đó không là chính quy.
(Q, , , q0, F) sao cho L = L(M). Giả sử M có m trạng thái. Chúng ta xem xét
xâu w, |w| = n, với n  m. Giả sử, w = a1a2…an, ai  . Với mỗi i = 0,1, …n, Ví dụ 4.14. Chứng minh ngôn ngữ L = {anbn | n  0} không chính quy.
giả sử (q0, a1a2…ai) = pi. Nghĩa là, pi là trạng thái của M sau khi đọc ký hiệu Giả sử L là ngôn ngữ chính quy. Thế thì, tồn tại OHD M thừa nhận L.
thứ i của w. Lưu ý, p0 = q0. Giả sử M có m trạng thái. Ta chọn xâu w = ambm, |w| = 2m  m. Khi đó,
M chỉ có m trạng thái khác nhau, trong khi xâu w cần đoán nhận có độ dài theo đinh lý bơm, tồn tại cách phân tích w thành xuy, với u   và |xu|
n. Bởi vì n  m, nên tồn tại i và j, với 0  i < j  m, sao cho pi = pj. Bây giờ  m. Suy ra, xu chỉ chứa toàn các ký hiệu a, nghĩa là u cũng chỉ chứa toàn
chúng ta sẽ phân tích w = xuy như sau: các ký hiệu a. Giả sử u = ak với k  1. Các xâu wi = xuiy, với i  0, sẽ không
thuộc L vì có số ký hiệu a khác số ký hiệu b. Như thế L không thỏa định lý
x = a1a2…ai
bơm, vậy L không là ngôn ngữ chính quy.
u = ai+1ai+2…aj
Ví dụ 4.15. Chứng minh ngôn ngữ L = {wwR | w  {a, b}*} không là
y = aj+1aj+2…an chính quy.
Bởi vì pi = pj, nên u bắt đầu tại pi và sau đó quay trở lại pi. Quan hệ Giả sử L là ngôn ngữ chính quy. Thế thì, tồn tại OHD M thừa nhận L. Giả
giữa các xâu và các trạng thái được minh họa trong hình 4.17. sử M có m trạng thái. Ta chọn xâu w = ambm bmam, |w| = 4m  m. Khi đó, theo
u = ai+1ai+2…aj đinh lý bơm, tồn tại cách phân tích w thành xuy, với u   và |xu|  m. Suy
ra, xu chỉ chứa toàn các ký hiệu a, nghĩa là u cũng chỉ chứa toàn các ký hiệu
a. Giả sử u = ak với k  1. Các xâu wi = xuiy, với i  0, sẽ không thuộc L vì có
x = a1a2…ai y = aj+1aj+2…an số ký hiệu a ở đầu xâu khác số ký hiệu a ở cuối xâu. Vậy L không phải là
q0 p qf ngôn ngữ chính quy.
Hình 4.17. Minh họa mọi xâu có độ dài lớn hơn số trạng thái đều lặp lại Ví dụ 4.16. Chứng minh ngôn ngữ L ={ak | k là số nguyên tố} không là
trên một trạng thái nào đó chính quy.
Lưu ý rằng, x có thể rỗng khi i = 0, y có thể rỗng khi j = n. Tuy nhiên, u Giả sử L là ngôn ngữ chính quy. Thế thì, tồn tại OHD M thừa nhận L.
không thể rỗng do j lớn hơn hẳn i, vậy u  . Ngoài ra, ta nhận thấy rằng |xu| Giả sử M có m trạng thái. Ta chọn xâu w = ap sao cho p > m + 1. Điều này
= j  m. hoàn toàn thực hiện được, vì số các số nguyên tố là vô hạn. Theo định lý
Bây giờ, xét xâu xuky với k  0. Nếu k = 0, thì ô-tô-mát M sẽ chuyển từ q0 bơm, tồn tại cách phân tích w thành xuy, với u   và |xu|  m. Đặt |u| = k,
đến pi khi đọc x và chuyển từ pi đến qf khi đọc y. Vậy xâu xy được thừa nhận. vậy |xy| = p - k. Theo định lý bơm, thì xuiy thuộc L với i  0. Xét xâu
Nếu k > 0, thì ô-tô-mát M sẽ chuyển từ q0 đến pi khi đọc x, lặp lại trên pi k xup-ky  L. Ta có:
lần khi đọc uk và chuyển từ pi đến qf khi đọc y. Vậy xâu xuky được thừa nhận. |xup-ky| = |x| + |up-k| + |y|
Như thế, k  0, xuky  L. Định lý được chứng minh.
= |xy| + |up-k|
= p - k + k*(p - k) = (p - k)(k + 1)

83 84
Do u  , nên |u| = k > 0, vậy k + 1 > 1. Ngoài ra, |u|  |xu|  m, vậy Bài 4.7. Cho L1 và L2 là các ngôn ngữ chính quy trên cũng bảng chữ ∑,
k  m. Ta lại có, p > m + 1, vậy p > k + 1. Hay p - k > 1. Cuối cùng, vì k + hãy chỉ ra thuật toán nhằm cho biết tồn tại các xâu thuộc ∑* không thuộc L1
1 > 1 và p - k > 1 nên |xup-ky| không phải là số nguyên tố. Vậy, xup-ky  và không thuộc L2.
L. Thế thì, L không phải là ngôn ngữ chính quy.
Bài 4.8. Xây dựng OHD nhỏ nhất nhất tương đương OHD được trình bày
trong bảng dịch chuyển sau:
4.6 Bài tập chương 4
 0 1
Bài 4.1. Xây dựng văn phạm chính quy tương ứng ô-tô-mát hữu hạn →A B F
sau: B G C
0 0 *C A C
q0 q1 D C G
E H F
0 1 1 F C G
G G E
1 0, 1
q2 q3 H G C
Bài 4.9. Xây dựng OHD nhỏ nhất nhất tương đương OHD trong
Hình vẽ 4.18. OHD cho bài tập 4.1 hình 4.19.
Bài 4.2. Xây dựng OHKD cho các văn phạm chính quy sau:
q1 0
a. S → 0A, A → 0A | 1A | 101 0
b. S → 00S | 11S | A, A → 010A | 010 q1 1
1
Bài 4.3. Xây dựng OHD cho các văn phạm chính quy sau: 0
a. S → 0S | 11 q3 0,1
q0
b. S → 1S | 00S | 010
1
Bài 4.4. Cho L1 là ngôn ngữ trên bảng chữ {a, b} gồm các xâu chứa ít 0 q5 0,1
nhất aa và L2 là ngôn ngữ trên bảng chữ {a, b} gồm các xâu bắt đầu
bởi bb. Hãy chứng minh rằng: q4 0
1
a. L1  L2 là ngôn ngữ chính quy.
q6 1
b. L1  L(ab*a) là ngôn ngữ chính quy.
c. L1R - L2 là ngôn ngữ chính quy. Hình 4.19. OHD cho bài tập 4.9

Bài 4.5. Cho L là ngôn ngữ chính quy, a là một ký hiệu, hãy chứng Bài 4.10. Xây dựng OHD nhỏ nhất tương đương OHKD trong
minh rằng L/{a} là một ngôn ngữ chính quy. hình 4.20.
a b c
Bài 4.6. Cho L1 và L2 là các ngôn ngữ chính quy, hãy chỉ ra thuật toán
 
nhằm xác định L1 và L2 chứa ít nhất một xâu chung. q0 q1 q2

85 86
Hình 4.20. OHKD cho bài tập 4.10
Bài 4.11. Chứng minh các ngôn ngữ sau không là chính quy:
a. {0n12n | n  0} Chương 5. Văn phạm phi ngữ cảnh
b. {0n11n | n > 0}
c. {anbmcn | m, n  0}
Trong các chương trước, chúng ta đã tìm hiểu ngôn ngữ chính quy và
Bài 4.12. Chứng minh các ngôn ngữ sau không là chính quy: các cách biểu diễn ngôn ngữ chính quy. Chúng ta đã thấy rằng ngôn ngữ
a. {an | n = m2, m  0} chính quy chỉ mô tả một lớp các ngôn ngữ tương đối đơn giản. Các ngôn
ngữ như {0n1n | n 0} hay {wwR | w  {0, 1}} không thuộc lớp các ngôn
b. {ww | w  {a, b}*} ngữ chính quy. Điều này đẫn đến việc nghiên cứu lớp ngôn ngữ rộng hơn,
c. {uuRv | u  {a, b}+, v  {a, b}*} được gọi là ngôn ngữ phi ngữ cảnh (context-free languages). Các ngôn
ngữ phi ngữ cảnh được mô tả bởi văn phạm, được gọi là văn phạm phi ngữ
cảnh (context-free grammars). Văn phạm phi ngữ cảnh đầu tiên được đề
xuất bởi Chomsky để mô tả các tính chất của ngôn ngữ tự nhiên, như tiếng
Anh hay tiếng Việt. Sau đó, văn phạm phi ngữ cảnh đã được phát triển
nhằm mô tả cú pháp của các ngôn ngữ lập trình. Hiện nay, văn phạm phi
ngữ cảnh đóng vai trò rất quan trọng trong việc xây dựng bộ phân tích cú
pháp của các chương trình dịch.

5.1 Văn phạm phi ngữ cảnh


5.1.1 Định nghĩa văn phạm và ngôn ngữ phi ngữ cảnh
Định nghĩa 5.1. Một văn phạm phi ngữ cảnh là một bộ bốn
G = (N, , R, S), trong đó:
- N tập các biến hay các ký hiệu không kết thúc.
-  là bảng chữ cái vào.
- S  N là biến đầu.
- R là tập các luật sinh hay sản xuất, mà mỗi luật sinh có dạng:
A→
trong đó A  N,   (N  )*.
Như thế, chúng ta nhận thấy rằng, đối với văn phạm chính quy mỗi luật
sinh có vế trái là một biến đơn, còn vế phải có dạng đặc biệt (tuyến tính
trái hoặc tuyến phải). Trong khi đối với văn phạm phi ngữ cảnh, vế trái
cũng là một biến đơn, nhưng vế phải là bất kỳ, không có sự giới hạn nào.

87 88
Với định nghĩa này chúng ta dễ dàng nhận thấy, một văn phạm chính quy Xét một dẫn xuất trong văn phạm G:
cũng là một văn phạm phi ngữ cảnh, tuy nhiên ngược lại thì không phải S ⇒ 0S 0 ⇒ 01 S 10 ⇒ 011 S 110 ⇒ 0110 S 0110 ⇒ 011010110
luôn luôn đúng. G G G G G

Định nghĩa 5.2. Ngôn ngữ L được gọi là ngôn ngữ phi ngữ cảnh nếu tồn Chúng ta nhận thấy rằng, văn phạm này sản sinh ra ngôn ngữ phi ngữ
tại một văn phạm phi ngữ cảnh G sao cho L = L(G). cảnh:
Như thế, một ngôn ngữ chính quy cũng là ngôn ngữ phi ngữ cảnh, hay nói L(G) = {wuwR | w  {0, 1}*, u  {, 0, 1}}
cách khác lớp các ngôn ngữ chính quy là tập con của lớp các ngôn ngữ phi Ví dụ 5.3. Cho văn phạm phi ngữ cảnh G = (N, , R, E) định nghĩa các
ngữ cảnh. Có thể minh họa điều này bằng hình 5.1. biểu thức đơn giản, trong đó, tập biến N = {E, I},  = {a, b, +, *, (, )}, E là biến
đầu, R gồm các luật sinh sau:
Ngôn ngữ chính quy E→I (1)
E→E+E (2)
Ngôn ngữ phi ngữ cảnh
E→E*E (3)
E→(E) (4)
Hình 5.1. Minh họa quan hệ giữa lớp ngôn ngữ chính quy và lớp ngôn ngữ
phi ngữ cảnh I→ a (5)

Ví dụ 5.1. Cho văn phạm phi ngữ cảnh G = ({S}, {0, 1}, R, S) có các luật I→ b (6)
sinh như sau: I→ aI (7)
S → 0S1 |  I→ bI (8)
Xét một dẫn xuất trong văn phạm G: Chúng ta có thể hiểu các luật sinh trên như sau. Luật sinh (1) nói rằng
S ⇒ 0S 1 ⇒ 00 S 11 ⇒ 000 S 111 ⇒ 0000 S 1111 ⇒ 00001111 một biểu thức là một định danh (biến). Luật sinh (2) mô tả một biểu thức
G G G G G là kết quả của phép cộng hai biểu thức. Luật sinh (3) mô tả một biểu thức
Chúng ta dễ dàng nhận thấy ngôn ngữ phi ngữ cảnh được sinh ra bởi là kết quả của phép nhân hai biểu thức. Luật sinh (4) mô tả một biểu thức
văn phạm G là: đặt giữa hai dấu đóng mở ngoặc cũng là một biểu thức. Các luật sinh (5)
đến (8) mô tả một định danh. Một định danh là một xâu không rỗng các ký
L(G) = {0n1n | n  0} hiệu a và b.
Ví dụ 5.2. Cho văn phạm phi ngữ cảnh G = ({S}, {0, 1}, R, S) có các luật
sinh như sau: 5.1.2 Dẫn xuất trái nhất và dẫn xuất phải nhất
S → 0S0 Để giới hạn sự lựa chọn các luật sinh trong quá trình dẫn xuất, nếu mỗi
bước biến bên trái nhất của dạng câu được thay thế thì ta gọi là dẫn xuất
S → 1S1 trái nhất. Tương tự, nếu mỗi bước biến bên phải nhất của dạng câu được
S→0 thay thế thì ta gọi là dẫn xuất phải nhất.
S→1 Ví dụ 5.4. Xét văn phạm phi ngữ cảnh G sau:
S→ S → aAB (1)

89 90
A → bBb (2) 5. Nếu một nút lá được gán nhãn là một ký tự rỗng  thì nó phải là nút
B→A (3) con duy nhất của nút cha của nó (hạn chế số lượng nút  trong cây
dẫn xuất).
B→ (4)
Ví dụ 5.5. Quay trở lại với văn phạm sinh ra các câu đối xứng trong ví dụ
Để dễ dàng xác định thứ tự các luật sinh được sử dụng trong dẫn xuất, 5.2, cây dẫn xuất sản sinh xâu 00111 được minh họa trong hình 5.2.
chúng ta đánh số các luật sinh. S
Xét dẫn xuất trái nhất sau:
1 2 3 2 4 4
0 S 1
S ⇒ aAB ⇒ abBbB ⇒ abAbB ⇒ abbBbbB ⇒ abbbbB ⇒ abbbb
Dẫn xuất trái nhất này cho xâu abbbb.
0 S 1
Xét dẫn xuất phải nhất sau:
1 4 2 3 2 4
S ⇒ aAB ⇒ aA ⇒ abBb ⇒ abAb ⇒ abbBbb ⇒ abbbb 1

Dẫn xuất phải nhất này cũng cho xâu abbbb. Hình 5.2. Cây dẫn xuất sản sinh xâu 00111

Hai dẫn xuất trái nhất và phải nhất trên là tương đương với nhau vì 5.2.2 Kết quả của cây dẫn xuất
chúng sinh ra cùng một xâu kết quả.
Nếu chúng ta đọc các nhãn của các nút lá từ trái qua phải sẽ nhận được
5.2 Cây dẫn xuất một xâu, được gọi là kết quả của cây dẫn xuất. Như thế, kết quả của một cây
dẫn xuất là một xâu chỉ gồm các ký hiệu kết thúc được dẫn xuất ra từ nút gốc
Có một dạng cây được sử dụng rất hữu ích để biểu diễn các dẫn xuất. (biến đầu).
Dạng cây này, được gọi là cây dẫn xuất hay cây cú pháp (parse tree), khi
được sử dụng trong chương trình dịch, là cấu trúc dữ liệu để biểu diễn các Ví dụ 5.6. Quay trở lại với văn phạm trong ví dụ 5.3, chúng ta xây
chương trình nguồn. Trong một chương trình dịch, cây dẫn xuất sẽ làm dễ dựng cây dẫn xuất có kết quả là (a + b) * bb trong hình 5.3.
E
dàng việc dịch các chương trình nguồn sang các mã thực thi.

5.2.1 Xây dựng cây dẫn xuất E * E

Định nghĩa 5.3. Cho văn phạm G = (N, , R, S). Cây dẫn xuất (còn
được gọi là cây cú pháp) là cây với các điều kiện sau: ( E ) I

1. Nút gốc được gán nhãn là biến đầu S.


E + E b I
2. Mỗi nút trong được gán nhãn là một biến thuộc N.
3. Mỗi nút lá được gán nhãn là một ký hiệu kết thúc thuộc  hoặc là I I b
một ký tự rỗng .
4. Nếu mỗi nút có nhãn là biến A  N và các con của nó được gán a b
nhãn theo thứ tự từ trái sang phải là X1, X2, …, Xn thì phải có luật
sinh A → X1X2…Xn trong R. Hình 5.3. Cây dẫn xuất sinh xâu (a + b) * bb

91 92
Định lý 5.1. Cho văn phạm phi ngữ cảnh G = (N, , R, S), một câu w Sau đó, chúng ta có thể xây dựng một cây với gốc là S, cho kết quả là w
*
như hình 5.5. Trong đó, các con của gốc là X1, X2,…Xn. Sự lựa chọn là hợp lý
được sinh ra bởi G, tức là S ⇒ w , thì tồn tại cây dẫn xuất có kết quả là w.
G bởi vì ta có dẫn xuất S → X1X2…Xn trong G.
Chứng minh: Chúng ta sẽ chứng minh bằng quy nạp theo số bước dẫn
xuất ra xâu w trong văn phạm G. S

Bước cơ sở: Nếu dẫn xuất chỉ là một bước, thì chỉ có một luật sinh
được sử dụng. Luật sinh đó phải là S → w. Giả sử w = a1a2…an. Luật sinh này X1 X2 Xn
sẽ tương ứng với cây có gốc là S và mỗi nút lá có nhãn là mỗi ký hiệu ai (Hình
5.4). Cây này sẽ thỏa mãn là cây dẫn xuất trong văn phạm G có kết quả là w.
T1 T2 Tn
Trong trường hợp đặc biệt w =  thì cây dẫn xuất chỉ có một nút lá duy nhất
có nhãn là . w1 w2 wn

S Hình 5.5. Cây dẫn xuất có kết quả w


Mỗi nút Xi là gốc cây dẫn xuất con với kết quả là wi. Trong trường hợp
a1 a2 an (1), Xi là một ký hiệu kết thúc, cây con này là một cây với chỉ duy nhất
một nút có nhãn Xi. Theo cách chia xâu w, trong trường hợp (1), thì wi = Xi.
Hình 5.4. Cây dẫn xuất cho kết quả a1a2…an
Vậy, cây dẫn xuất con có kết quả là wi.
Bước quy nạp: Bây giờ, giả sử rằng định lý là đúng với mọi xâu x
Trong trường hợp (2), Xi là một biến, thì chúng ta sử dụng giả thuyết quy
được dẫn xuất ra từ X sau n bước với X  N, nghĩa là tồn tại cây dẫn xuất
tương ứng cho kết quả là x. nạp rằng phải tồn tại cây dẫn xuất có gốc Xi cho kết quả là wi.
Bằng cách ghép kết quả của các cây con ta có được kết quả của cây dẫn
Xét xâu w được dẫn xuất ra từ S sau n + 1 bước. Chúng ta cần chứng
xuất có gốc S là w1w2…wn, nghĩa là w.
minh rằng tồn tại cây dẫn xuất cho kết quả là xâu w. Xét bước đầu tiên của
dẫn xuất sinh ra w, bước này sẽ sử dụng một trong các luật sinh có dạng Ngược lại, chúng ta cũng có thể chỉ ra rằng luôn có thể xây dựng một dẫn
S → X1X2…Xn, trong X1, X2,…Xn hoặc là biến thuộc N hoặc là ký hiệu kết xuất từ một cây dẫn xuất. Chúng ta sẽ chỉ xem xét cách xây dựng một dẫn
thúc thuộc . xuất trái nhất từ một cây dẫn xuất, cách xây dựng một dẫn xuất phải nhất
cũng được thực hiện tương tự.
Chúng ta chia xâu w thành các xâu w1, w2, …, wn sao cho:
Định lý 5.2. Cho văn phạm phi ngữ cảnh G = (N, , R, S), và giả sử có
(1) Nếu Xi là một ký hiệu kết thúc, thì wi = Xi, nghĩa là wi chỉ chứa một
một cây dẫn xuất cho kết quả là w  *, thì tồn tại một dẫn xuất trái nhất
ký hiệu kết thúc từ luật sinh. *
S ⇒ w trong văn phạm G.
(2) Nếu Xi là một biến, thì wi là xâu mà được dẫn xuất ra từ biến Xi. G

Nghĩa là, dẫn xuất này có nhiều nhất là n bước từ dẫn xuất n + 1
Chứng minh: Chúng ta sẽ chứng minh bằng quy nạp theo chiều cao của
bước sinh ra w. Thật vậy, dẫn xuất này không thể có n + 1 bước,
cây dẫn xuất.
bởi vì bước đầu tiên sử dụng luật sinh S → X1X2…Xn, không thể
thuộc dẫn xuất sinh ra wi. Áp dụng giả thuyết quy nạp sinh xâu wi Bước cơ sở: Khi cây dẫn xuất có chiều cao bằng 1. Trong trường hợp
với n bước dẫn xuất, ta có cây dẫn xuất Ti với kết quả là wi. này, cây dẫn xuất có dạng như trong hình 5.4, với nút gốc là S và các nút lá
đọc từ trái qua phải là w. Theo định nghĩa cây dẫn xuất, thì S → w phải là một
luật sinh. Như thế, S ⇒ w là dẫn xuất trái nhất một bước từ S.

93 94
Bước quy nạp: Giả sử định lý đúng với cây dẫn xuất có chiều cao nhỏ …
hơn n, với n > 1. Cần chứng minh định lý cho trường hợp cây dẫn xuất có
w1w2…wi-1wiXi+1…Xn
chiều cao n. Khi đó, cây dẫn xuất có dạng như trong hình 5.5, có nút gốc
là S và các nút con X1, X2, …, Xn từ trái qua phải. Các Xi có thể có hai khả Như vậy, trong cả hai trường hợp, chúng ta có dẫn xuất trái nhất:
năng: *
S⇒ ww wX X X
(1) Nếu Xi là một ký hiệu kết thúc, thì đặt wi = Xi. 1 2 i i+ 1 i+2 n

Khi i = k, thì chúng ta có dẫn xuất trái nhất sinh ra w từ S.


(2) Nếu Xi là một biến, thì nó phải là gốc của cây con mà cho kết quả là
dãy ký hiệu kết thúc, đặt là wi. Lưu ý rằng trong trường hợp này, Ví dụ 5.7. Xây dựng dẫn xuất trái nhất từ cây trong hình 5.3.
cây con có chiều cao nhỏ hơn n. Như thế, áp dụng giả thuyết quy E⇒E*E⇒(E)*E⇒(E+E)*E⇒(I+E)*E
*
nạp đối với cây con này, chúng ta có dẫn xuất trái nhất X i ⇒ w i ⇒(a+E)*E⇒(a+I)*E⇒(a+b)*E
Lưu ý rằng w = w1w2…wn. ⇒ ( a + b ) * I ⇒ ( a + b ) * bI ⇒ ( a + b ) * bb
Chúng ta xây dựng dẫn xuất trái nhất cho kết quả w. Chúng ta bắt đầu bởi Một định lý tương tự cho phép chuyển cây dẫn xuất thành dẫn xuất
dẫn xuất S ⇒ X1X2…Xn. Với mỗi i = 1, 2, …, n, chúng ta cần chỉ ra dẫn xuất phải nhất. Việc xây dựng dẫn xuất phải nhất từ cây tương tự như xây dựng
trái nhất sau: dẫn xuất trái nhất. Tuy nhiên, sau khi thực hiện bước dẫn xuất phái nhất S
* ⇒ X1X2…Xn, chúng ta thực hiện dẫn xuất từ Xn cho đến X1.
S ⇒ w 1 w 2 w i X i+ 1 X i+ 2 X n
Định lý 5.3. Cho văn phạm phi ngữ cảnh G = (N, , R, S), và giả sử có
Chúng ta sẽ chứng minh điều này bằng phương pháp quy nạp theo giá một cây dẫn xuất cho kết quả là w  *, thì tồn tại một dẫn xuất phải nhất
trị của i. Đối với bước cơ sở, i = 0, chúng ta đã luôn có dẫn xuất trái nhất *
S ⇒ w trong văn phạm G.
S ⇒ X1X2…Xn. Đối với bước quy nạp, giả sử rằng chúng ta có dẫn xuất G

trái nhất: Chứng minh định lý 5.3 tương tự như chứng minh định lý 5.2 ở trên.
*
S⇒ ww w XX X
1 2 i −1 i i +1 n
5.3 Sự nhập nhằng trong văn phạm
(a) Nếu Xi là một ký hiệu kết thúc, Xi là dãy ký hiệu wi. Vậy chúng ta
5.3.1 Văn phạm nhập nhằng
có dẫn xuất trái nhất:
*
Với một văn phạm G, một xâu w thuộc L(G) có thể là kết quả của
S⇒ ww wX X X nhiều cây dẫn xuất khác nhau. Điều đó có nghĩa là xâu w có thể được phân
1 2 i i +1 i +2 n
tích cú pháp bằng nhiều cách khác nhau, tức là xâu w có thể được hiểu bởi
(b) Nếu Xi là một biến, tiếp tục thực hiện dẫn xuất trái nhất từ Xi cho
các cách khác nhau. Chúng ta có nói xâu w là nhập nhằng.
đến khi đạt được wi. Nghĩa là, dẫn xuất trái nhất:
Định nghĩa 5.4. Một văn phạm G = (N, , R, S) được gọi là nhập
X i ⇒ 1 ⇒ 2 ⇒ … ⇒ w i nhằng (ambiguity) nếu có ít nhất một xâu w  * là kết quả của hai cây dẫn
Chúng ta thực hiện dẫn xuất trái nhất như sau: xuất khác nhau có gốc là S. Nếu mỗi xâu có nhiều nhất một cây dẫn xuất
w1w2…wi-1XiXi+1…Xn ⇒ trong văn phạm, thì văn phạm được gọi là không nhập nhằng.

w1w2…wi-11Xi+1…Xn ⇒ Ví dụ 5.8. Xét văn phạm cho trong ví dụ 5.3.

w1w2…wi-12Xi+1…Xn ⇒ E→I|E+E|E*E|(E)

95 96
I → a | b | aI | bI nhập nhằng hay không cũng như cho phép loại bỏ sự nhập nhằng của một
văn phạm bất kỳ. Tuy nhiên, đối với ngôn ngữ lập trình, tồn tại các kỹ
Các luật sinh E → E + E | E * E cho phép sinh ra các biểu thức sử dụng các
thuật cho phép loại bỏ sự nhập nhằng.
toán tử + và * trong các thứ tự khác nhau. Xét dạng câu I + I * I, có hai dẫn
xuất khác nhau từ E như sau: Sự nhập nhằng của văn phạm trong ví dụ 5.3 là rất điển hình trong xây
dựng ngôn ngữ lập trình. Quay trở lại ví dụ này, chúng ta cần xác định các
(1) E ⇒ E + E ⇒ I + E ⇒ I + E * E ⇒ I + I * E ⇒ I + I * I
nguyên nhân gây nên sự nhập nhằng của văn phạm là:
(2) E ⇒ E * E ⇒ E * I ⇒ E + E * I ⇒ E + I * I ⇒ I + I * I
1. Thứ tự ưu tiên của các toán tử đã không được mô tả. Chúng ta
Hay chúng ta biểu diễn hai cây dẫn xuất tương ứng với các dẫn xuất trên nhận thấy, trong hình 5.6 (a) toán tử * được thực hiện trước khi
trong hình 5.6. thực hiện toán tử +, trong khi trong hình 5.6 (b) toán tử + được
E E thực hiện trước khi thực hiện toán tử *. Chúng ta cần mô tả văn
phạm sao cho chỉ có cây dẫn xuất trong hình 5.6 (a) cho kết quả
I + I * I.
E + E E * E
2. Tính chất kết hợp của các toán tử có cùng độ ưu tiên có thể được
thực hiện từ trái qua hoặc từ phải qua. Đối với toán tử + và toán
I E * E E + E I
tử * thì không gây ra vấn đề, tuy nhiên chẳng hạn đối với toán
tử − thì có thể gây nên sự nhập nhằng. Ví dụ, 8 - 2 - 2 được thực
I I I I hiện như thế nào? Theo quy ước thì tính kết hợp các toán tử +
a) b) và − được thực hiện từ trái qua.

Hình 5.6. Hai cây dẫn xuất cho cùng kết quả I + I * I Để loại bỏ sự nhập nhằng trong văn phạm trên, cần thêm vào một số biến
để mô tả thứ tự ưu tiên của các toán tử:
Như thế, văn phạm trong ví dụ 5.3 là nhập nhằng. Hai dẫn xuất này có ý
nghĩa hoàn toàn khác nhau: dẫn xuất (1) thực hiện nhân hai biểu thức thứ 1. Biến F biểu diễn biểu thức không thể bị tách rời bởi bất kỳ toán tử
hai và thứ ba trước, sau đó cộng với biểu thức thứ nhất; trong khi dẫn xuất nào liền kề. Biến F sẽ là một định danh (các ký tự của một định
(2) thực hiện cộng hai biểu thức thứ nhất và thứ hai trước, sau đó nhân với danh là không thể tách rời) hoặc một biểu thức được đặt trong cặp
biểu thức thứ ba. Nếu chúng ta thay các định danh (I) bởi các giá trị cụ thể, dấu ngoặc (biểu thức này không thể bị tách rời bởi các toán tử ở
chẳng hạn 2 + 5 * 3. Khi đó, dẫn xuất (1) thực hiện bên ngoài dấu ngoặc). Vậy, chúng ta có luật sinh: F → I | ( E ).
2 + (5 * 3) = 17, trong khi dẫn xuất (2) thực hiện (2 + 5) * 3 = 21. Tất
2. Biến T biểu diễn biểu thức không thể bị tách rời bởi toán tử + liền
nhiên, chúng ta dễ dàng nhận thấy rằng dẫn xuất (1) định giá đúng biểu thức kề. Trong văn phạm này, chỉ có hai toán tử * và +, nên T là một
số học. phép nhân của một hoặc nhiều F. Như thế, toán tử * được ưu tiên
Chúng ta nhận thấy rằng thứ tự thực hiện của toán tử * và + trong hai dẫn hơn toán tử +. Vậy, chúng ta có luật sinh: T → F | T * F.
xuất trên là bất kỳ. Tuy nhiên, thứ tự thực hiện của hai toán tử này phải xác 3. Một biểu thức E có thể là biểu thức bất kỳ. Như thế, một biểu
định, nghĩa là toán tử * phải được thực hiện trước toán tử +. thức là phép cộng của một hoặc nhiều T. Vậy, chúng ta có luật
sinh: E → T | E + T.
5.3.2 Loại bỏ sự nhập nhằng trong văn phạm
Cuối cùng, chúng ta có văn phạm không nhập nhằng như sau:
Cần phải loại bỏ sự nhập nhằng trong văn phạm khi định nghĩa ngôn
ngữ. Hiện tại, không tồn tại thuật toán cho phép xác định một văn phạm là F→I|(E)

97 98
T→F|T*F (1) Có số ký hiệu a bằng số ký hiệu b và có số ký hiệu c bằng số ký
E→T|E+T hiệu d, hoặc

I → a | b | aI | bI (2) Có số ký hiệu a bằng số ký hiệu d và có số ký hiệu b bằng số ký


hiệu c.
Ví dụ 5.9. Văn phạm không nhập nhằng trên chỉ cho phép xây dựng duy
nhất một cây dẫn xuất (hình 5.7) cho kết quả I + I * I. Chúng ta dễ dàng xây dựng được văn phạm sản sinh G ra ngôn ngữ L như
sau:
E
S → AB | C
E + T A → aAb | ab
B → cBd | cd
I T * F C → aCd | aDd
D → bDc | bc
F I
Chẳng hạn, chúng ta thực hiện hai dẫn xuất trái nhất sản sinh xâu
aabbccdd như sau:
I
(1) S ⇒ AB ⇒ aAbB ⇒ aabbB ⇒ aabbcBd ⇒ aabbccdd
Hình 5.7. Cây dẫn xuất cho kết quả I + I * I
(2) S ⇒ C ⇒ aCd ⇒ aaDdd ⇒ aabDcdd ⇒ aabbccdd
5.3.3 Sự nhập nhằng cố hữu Chúng ta cũng có thể xây dựng hai cây dẫn xuất cho kết quả
Định nghĩa 5.5. Một ngôn ngữ phi ngữ cảnh L được gọi là nhập nhằng cố xâu aabbccdd trong hình 5.8. Như vậy, văn phạm này là nhập nhằng.
hữu, nếu tất cả các văn phạm của nó nhập nhằng. Nếu một văn phạm của L là S S
không nhập nhằng, thì L là ngôn ngữ không nhập nhằng.
Như vậy, một ngôn ngữ phi ngữ cảnh nhập nhằng cố hữu thì không tồn C
tại văn phạm không nhập nhằng mô tả nó. Nếu văn phạm của một ngôn A B
ngữ nhập nhằng, không có nghĩa là ngôn ngữ đó nhập nhằng, bởi vì có thể tồn
tại văn phạm khác mô tả ngôn ngữ đó nhưng không nhập nhằng. a A b c B d a C d

Trong phạm vi giáo trình này, chúng ta sẽ không chứng minh một ngôn
a c a D d
ngữ nhập nhằng cố hữu. Tuy nhiên, chúng ta sẽ xem xét một vài ví dụ và giải b d
thích tại sao tất cả các văn phạm sản sinh ra ngôn ngữ là nhập nhằng.
b D c
Ví dụ 5.10. Ngôn ngữ
L = {anbncmdm | n ≥ 1, m ≥ 1}  {anbmcmdn | n ≥ 1, m ≥ 1}
b c
là nhập nhằng cố hữu.
a) b)
Nghĩa là, ngôn ngữ L gồm các xâu có dạng a+b+c+d+ sao cho:
Hình 5.8. Hai cây dẫn xất cho kết quả xâu aabbccdd.

99 100
Chúng ta nhận thấy rằng các xâu của ngôn ngữ phải được sinh ra bởi 5.4.1 Định nghĩa ngôn ngữ lập trình
một trong hai cách: Chúng ta đã thấy rằng nhiều mẫu đơn giản của ngôn ngữ lập trình có thể
- số ký hiệu a và số ký hiệu b được sinh ra phải bằng nhau, và số ký được mô tả bởi biểu thức chính quy, chẳng hạn như các định danh. Tuy
hiệu c và số ký hiệu d được sinh ra phải bằng nhau, hoặc nhiên, các cấu trúc quan trọng và phức tạp trong ngôn ngữ lập trình lại
không thể được mô tả bởi biểu thức chính quy. Chúng ta sẽ xem xét một số
- số ký hiệu a và số ký hiệu d được sinh ra phải bằng nhau, và số ký
ví dụ cụ thể dưới đây.
hiệu b và số ký hiệu c được sinh ra phải bằng nhau.
Ví dụ 5.12. Chúng ta sử dụng văn phạm phi ngữ cảnh sau để mô tả các cấu
Trong văn phạm G ở trên, số ký hiệu a và số ký hiệu b được sinh ra
trúc sử dụng hai ký hiệu { và } trong ngôn ngữ lập trình C.
bằng nhau bởi biến A. Cũng còn có các cách khác để thực hiện điều đó, tuy
nhiên, các cách này cũng không thay đổi bản chất của văn phạm. Thật vậy, S → SS | { S } | 
chẳng hạn chúng ta xét một số cách: Văn phạm này cho phép định nghĩa các khối lệnh bắt đầu bởi { và kết
- Chúng ta có thể thay thế luật sinh A → ab bởi luật sinh thúc bởi } tương ứng. Luật sinh S → SS mô tả các khối lệnh đi liền nhau,
A → aaabbb. trong khi luật sinh S → {S} mô tả các khối lệnh lồng nhau.
- Chúng ta có thể sử dụng thêm các biến A1 và A2 hỗ trợ biến A, như Nếu chúng ta thay thế cặp ký hiệu { và } bởi cặp ký hiệu ( và ) thì văn
A1 → aA2b | ab; A2 → aA1b | ab. phạm trên cho phép mô tả việc sử dụng các cặp dấu ngoặc trong các biểu
thức số học.
- Chúng ta có thể sử dụng biến A sinh ra số các ký hiệu a và b không
bằng nhau. Chẳng hạn, chúng ta bắt đầu bởi luật sinh S → AbB và Ví dụ 5.13. Luật sinh sau cho phép mô tả cấu trúc lệnh rẽ nhánh trong các
sau đó sử dụng A → aAb | a. ngôn ngữ lập trình C.
Cũng như thế, chúng ta cũng có thể lý giải tương tự cho các biến B, C và <selection-statement> →
D. Vì thế, cho dù có các thay đổi văn phạm sản sinh L, thì nó vẫn sinh ra các IF ( <expr> ) <statement>
xâu có dạng anbncndn bởi hai cách khác nhau.
| IF ( <expr> ) <statement> ELSE <statement>
Ví dụ 5.11. Tương tự, chúng ta cũng có thể nhận thấy rằng ngôn ngữ
phi ngữ cảnh L = {aibjck | i = j hoặc j = k} là nhập nhằng cố hữu. Thật | SWITCH ( <expr> ) <statement>
vậy, đối với bất kỳ văn phạm phi ngữ cảnh G nào sản sinh L, phải có một Trong đó, các ký hiệu biến được đặt giữa cặp ký hiệu < và >, IF, ELSE,
phương pháp sinh ra các xâu dạng aibick và một phương pháp sinh ra các SWITCH là các từ khóa, ( và ) là các ký hiệu kết thúc. Biến <expr> dùng để
xâu dạng aibkck. Như thế, sẽ luôn có hai cách khác nhau để sinh ra các xâu định nghĩa các biểu thức và biến <statement> dùng để định nghĩa các lệnh.
có dạng aibici. Tuy nhiên, trong đoạn văn phạm này, hai biến này chưa được định nghĩa.
Phần thứ nhất của vế phải mô tả lệnh IF không có ELSE, phần thứ hai mô tả
5.4 Ứng dụng của văn phạm phi ngữ cảnh lệnh IF có ELSE, và phần cuối cùng mô tả lệnh SWITCH.
Văn phạm phi ngữ cảnh ban đầu được đề xuất bởi Chomsky để mô tả Ví dụ 5.14. Chúng ta xem xét cách sử dụng văn phạm phi ngữ cảnh mô tả
ngôn ngữ tự nhiên, nhưng sau đó mục đích này đã không được phát triển. các lệnh lặp trong ngôn ngữ lập trình C như sau:
Tuy nhiên, văn phạm phi ngữ cảnh lại được sử dụng để mô tả một cách đệ
quy các khái niệm trong lĩnh vực tin học. Một trong những ứng dụng quan <iteration-statement> →
trọng là định nghĩa ngôn ngữ lập trình và xây dựng bộ phân tích cú pháp. WHILE ( <expr> ) <statement>
| DO <statement> WHILE ( <expr> );

101 102
| FOR ( ; ; ) <statement> - Danh sách các vế phải tương ứng với một vế trái kết thúc bởi dấu
| FOR ( ; ; <expr> ) <statement> chấm phẩy.

| FOR ( ; <expr> ; ) <statement> - Các ký hiệu kết thúc được đặt trong dấu nháy đơn, chẳng hạn ký
hiệu ‘\n’ hay ‘+’. Các đơn vị từ vựng xuất hiện trong chương trình
| FOR ( ; <expr> ; <expr> ) <statement> nguồn được xác định bởi bộ phân tích cú pháp và được chuyển đến
| FOR ( <expr> ; ; ) <statement> bộ phân tích cú pháp, chẳng hạn INTEGER.

| FOR ( <expr> ; ; <expr> ) <statement> program:


program expr '\n' {printf("%d\n", $2);}
| FOR ( <expr> ; <expr> ; ) <statement> |
| FOR ( <expr> ; <expr> ; <expr> ) <statement> ;
expr:
Trong đó, WHILE, DO, FOR là các từ khóa, (, ) và ; là các ký hiệu kết INTEGER {$$ = $1;}
thúc. Tương tự như trong ví dụ 5.13, hai biến <expr> và <statement> | expr '+' expr {$$ = $1 + $3;}
chưa được định nghĩa. Văn phạm này lần lượt mô tả các cấu trúc lệnh lặp | expr '-' expr {$$ = $1 - $3;}
;
WHILE, DO WHILE, và FOR.
Hình 5.9. Một đoạn đầu vào của công cụ Yacc
5.4.2 Công cụ sinh bộ phân tích cú pháp Yacc/Bison
Yacc sử dụng hai ngăn xếp trong bộ nhớ: ngăn xếp ký hiệu và ngăn xếp
Trong chương 3, chúng ta đã tìm hiểu việc sử dụng công cụ Lex/Flex giá trị. Ngăn xếp ký hiệu chứa các ký hiệu kết thúc và ký hiệu không kết
để sinh bộ phân tích từ vựng của một chương trình nguồn. Một thành phần thúc, biểu diễn trạng thái phân tích hiện tại. Ngăn xếp giá trị chứa các giá trị
khác rất quan trọng của một chương trình dịch là bộ phân tích cú pháp tương ứng của các ký hiệu trong ngăn xếp ký hiệu.
(parser), cho phép tạo cây cú pháp hay cây dẫn xuất từ chương trình
Các đoạn mã nguồn C tương ứng với các luật sinh được đặt giữa cặp dấu
nguồn. Yacc/Bison là các công cụ cho phép sinh bộ phân tích cú pháp như
mở và đóng ngoặc nhọn. Trong các đoạn mã nguồn C, chúng ta có thể truy
thế. Yacc được cung cấp bởi hệ điều hành UNIX, trong khi Bison là sản
cập đến các vị trí trong ngăn xếp giá trị bằng cách sử dụng $1 cho phần tử
phẩm của GNU.
thứ nhất trong vế phải của luật sinh, $2 cho phần tử thứ hai… $$ chỉ đến
Đầu vào của Yacc/Bison là văn phạm phi ngữ cảnh, trong đó mỗi luật đỉnh của ngăn xếp.
sinh được gắn với một đoạn mã nguồn C. Khi một nút tương ứng của cây
Chẳng hạn, luật sinh đầu tiên
cú pháp được tạo ra thì đoạn mã nguồn tương ứng với luật sinh đó sẽ được
thực thi. program: program expr '\n' {printf("%d\n", $2);}

Ví dụ 5.15. Chúng ta xem xét đoạn đầu vào của Yacc nhằm phân tích các nói rằng một chương trình (program) chứa không hoặc nhiều biểu thức
biểu thức số học đơn giản trong hình 5.9. (expr). Mỗi biểu thức kết thúc bởi ký hiệu sang dòng mới. Khi gặp ký hiệu
sang dòng mới, chúng ta in giá trị của biểu thức.
Lưu ý các sự tương ứng giữa các quy ước mô tả văn phạm của công cụ
Yacc và của chúng ta như sau: Khi chúng ta áp dụng luật sinh

- Dấu hai chấm thay thế cho ký hiệu →. expr: expr '+' expr {$$ = $1 + $3;}

- Tất cả các luật sinh có vế trái giống nhau được nhóm lại với nhau, chúng ta thay thế vế phải của luật sinh trong ngăn xếp ký hiệu bởi vế
các vế phải được ngăn cách bởi ký hiệu |. trái của cùng luật sinh. Trong trường hợp này, chúng ta lấy ra
expr ‘+’ expr và đưa vào expr. Câu lệnh $$ = $1 + $3 thực hiện cộng giá

103 104

trị tương ứng của hai biểu thức, lấy ba phần tử của expr ‘+’ expr ra khỏi
2. Ký hiệu X được gọi là đạt đến được, nếu tồn tại S ⇒ X với
ngăn xếp giá trị, và đưa vào ngăn xếp giá trị tổng tính được.
,   (N  )*. Ngược lại, X được gọi là ký hiệu không đạt đến
5.5 Dạng chuẩn của văn phạm phi ngữ cảnh được.

Đối với một ngôn ngữ phi ngữ cảnh L, văn phạm sản sinh L không nhất Như thế, một ký hiệu hữu sinh thì nó sẽ hữu sinh và đạt đến được. Ví
thiết là duy nhất. Chúng ta có thể mong muốn các luật sinh của văn phạm có dụ 5.16. Xét văn phạm:
dạng dạng đặc biệt nào đó. Khi chúng ta đưa ra các giới hạn đối với vế phải
S → aSb | A | ab
của các luật sinh, chúng ta nói văn phạm có dạng chuẩn.
A → aA
Chúng ta sẽ chỉ ra rằng bất kỳ một phi ngữ cảnh nào không chứa xâu
rỗng  cũng được sinh ra bởi chỉ các luật sinh có dạng A → BC hoặc Ngoại trừ ký hiệu A, các ký hiệu còn lại là hữu sinh: a và b sinh ra
A → a, với A, B, C là các biến và a là ký hiệu kết thúc. Văn phạm với các chính chúng, S sinh ra ab, trong khi không thể biến đổi A thành xâu các ký
luật sinh như thế được gọi là dạng chuẩn Chomsky. Để có được văn phạm hiệu kết thúc được.
dạng chuẩn như thế chúng ta cần phải thực hiện một số bước giản lược: Ví dụ 5.17. Xét văn phạm:
1. Loại bỏ các ký hiệu vô ích, là các biến hoặc ký hiệu không kết thúc S→A
mà không xuất hiện trong bất kỳ dẫn xuất nào sinh ra xâu từ biến
đầu. A → aA | 

2. Loại bỏ các luật sinh , là các luật sinh có dạng A → , với A là một B→b
biến. 
Ký hiệu B là không đạt đến được vì không thể có được S ⇒ B , với
3. Loại bỏ các luật sinh đơn vị, là các luật sinh có dạng A → B, với A ,   (N  )*.
và B là các biến.
Để loại bỏ các ký hiệu vô ích, trước hết chúng ta cần xác định các ký hiệu
5.5.1 Loại bỏ ký hiệu vô ích hữu ích.
Cho văn phạm phi ngữ cảnh G = (N, , R, S). Một ký hiệu X  N  Xác định ký hiệu hữu sinh
 được gọi là hữu ích nếu tồn tại dẫn xuất: Cho văn phạm phi ngữ cảnh G = (N, , R, S). Các ký hiệu hữu sinh
  được xác định như sau:
S ⇒  X  ⇒ w , với ,   (N)* và w  *.
1. Mỗi ký hiệu kết thúc thuộc  là hữu sinh, bởi vì nó có thể sinh ra
Nghĩa là, một ký hiệu là hữu ích nếu nó xuất hiện trong ít nhất một dẫn chính nó.
xuất sinh xâu thuộc ngôn ngữ. Ngược lại, một ký hiệu được gọi là vô ích. Rỏ
2. Nếu tồn tại luật sinh A →  và mọi ký hiệu của  là hữu sinh thì A
ràng, nếu chúng ta loại bỏ các ký hiệu vô ích thì sẽ không ảnh hưởng đến
là hữu sinh. Lưu ý rằng khi  =  thì hiển nhiên A hữu sinh. Lặp lại
ngôn ngữ sinh ra bởi văn phạm, vì chúng không tham gia vào quá trình
bước này cho đến khi không xác định thêm các ký hiệu hữu sinh
sinh các xâu thuộc ngôn ngữ.
nào nữa.
Chúng ta xét hai loại ký hiệu vô ích sau:
Chúng ta dễ dàng nhận thấy các bước trên xác định tất cả các ký hiệu

1. Ký hiệu X được gọi là hữu sinh, nếu tồn tại X ⇒ w với w   . *
hữu sinh và chỉ các ký hiệu hữu sinh trong văn phạm G.
Ngược lại, X được gọi là ký hiệu vô sinh. Lưu ý rằng mọi ký hiệu
kết thúc là hữu sinh.
105 106

Xác định ký hiệu đạt đến được
Do A không bị loại bỏ bởi bước 1, nên tồn tại A ⇒ w , w  *. Như thế,
G
Cho văn phạm phi ngữ cảnh G = (N, , R, S). Các ký hiệu đạt đến được có 
thể được xác định như sau: các ký hiệu tham gia vào dẫn xuất này đều là không vô sinh, nên A ⇒ w
G'
1. S hiển nhiên là ký hiệu đạt đến được. 
Hơn nữa, A không bị loại bỏ bởi bước 2, nên tồn tại S ⇒ A . Như
2. Giả sử chúng ta đã xác định được A là biến đạt đến được. Khi đó, G 1

với tất cả các luật sinh  →  mà  chứa A thì các ký hiệu thuộc  thế, tất cả các ký hiệu trong dẫn xuất này đều đạt đến được, nghĩa là
là các ký hiệu đạt đến được. Lặp lại bước này cho đến khi không 
S ⇒ A . Các ký hiệu trong  và  đều đạt đến được, tức là các ký hiệu
xác định thêm các ký hiệu đạt đến được nào nữa. G'

này thuộc N1  1, vậy các ký hiệu này là hữu sinh. Khi đó, ta có
Rỏ ràng, các bước trên xác định tất cả các ký hiệu đạt đến được và chỉ các  
đạt đến được trong văn phạm G. S ⇒  A  ⇒ xwy
G' G'
Loại bỏ ký hiệu vô ích
Chúng ta kết luận rằng A là ký hiệu có ích. Bởi vì việc chọn A là bất kỳ,
Cho văn phạm phi ngữ cảnh G = (N, , R, S), giả sử L(G)  , nghĩa là G nghĩa là tất cả các ký hiệu trong G’ đều là có ích.
sản sinh ra ít nhất một xâu. Chúng ta sẽ thực hiện việc loại bỏ các ký hiệu vô
ích trong G bởi hai bước sau: Cần tiếp tục chứng minh rằng G và G’ tương đương, nghĩa là L(G)
= L(G’). Hay cần chứng minh: L(G’)  L(G) và L(G)  L(G’).
1. Loại bỏ tất cả các ký hiệu vô sinh và các luật sinh chứa một hoặc
nhiều ký hiệu này. - L(G’)  L(G): Điều này là hiển nhiên vì G’ nhận được bằng
cách loại bỏ các ký hiệu và luật sinh trong G.
2. Loại bỏ tất cả các ký hiệu không đạt đến được và các luật sinh chứa
một hoặc nhiều ký hiệu này. - L(G)  L(G’): Cần chứng minh w  L(G) thì w  L(G’). Thật

Định lý 5.4. Cho văn phạm phi ngữ cảnh G = (N, , R, S), với L(G) vậy, vì w  L(G) nên tồn tại S ⇒ w . Rỏ ràng rằng tất cả các ký
G
  thì tồn tại văn phạm phi ngữ cảnh tương đương G’ = (N’, hiệu tham gia vào dẫn xuất này đều là hữu sinh và đạt đến được,
’, R’, S) không chứa các ký hiệu vô ích. 
vậy S ⇒ w . Như thế, w  L(G’).
Chứng minh: Chúng ta sẽ thực hiện hai bước loại bỏ các ký hiệu vô ích G'

trong G. Lưu ý, khi loại bỏ các ký hiệu vô ích, cần phải thực hiện loại bỏ theo
1. Trước hết, chúng ta loại bỏ ký hiệu vô sinh và các luật sinh chứa đúng thứ tự: loại bỏ các ký hiệu vô sinh trước, sau đó loại bỏ các ký hiệu
một hoặc nhiều ký hiệu này, chúng ta thu được văn phạm không đạt đến được.
G1 = (N1, 1, R1, S). Lưu ý biến S không thể bị loại bỏ vì G phải Ví dụ 5.18. Xét văn phạm phi ngữ cảnh G:
sản sinh ít nhất một xâu (L(G)  ).
S → aSb | ab | A
2. Sau đó, tiếp tục thực hiện loại bỏ tất cả các ký hiệu không đạt đến
A → aAB
được và các luật sinh chứa một hoặc nhiều ký hiệu này trong G1,
chúng ta thu được văn phạm G’. B→b
Giả sử A là ký hiệu bất kỳ trong G’, nghĩa là A  N’  ’. Cần chỉ ra rằng Chúng ta dễ dàng xác định các ký hiệu hữu sinh gồm a, b, B và S. Vậy ký
A là ký hiệu có ích trong G’, tức là A phải tham gia vào quá trình sinh xâu gồm hiệu A còn lại là vô sinh. Loại bỏ A cùng các luật sinh chứa nó. Văn phạm
các ký hiệu kết thúc trong G’. G còn lại các luật sinh:

107 108
S → aSb | ab • Nếu A → B1B2…Bn là luật sinh trong R thì thêm vào R’ các luật sinh
B→b có dạng A → x1x2…xn trong đó mỗi xi thay thế Bi thỏa mãn các điều
kiện sau:
Khi đó, các ký hiệu đạt đến được gồm S, a và b, còn lại B là ký hiệu
không đạt đến được. Vậy loại bỏ B cùng các luật sinh chứa nó. Cuối cùng, văn - Nếu Bi là biến không triệt tiêu được thì cho xi = Bi.
phạm G chỉ còn lại các luật sinh: - Nếu Bi là biến triệt tiêu được thì cho xi =  (khi cho xi =  nghĩa
S → aSb | ab là Bi sẽ vắng mặt) hoặc xi = Bi.

Nếu chúng ta thực hiện việc loại bỏ không đúng thứ tự. Giả sử loại bỏ các - Không cho tất cả các xi = , nghĩa là nếu A →  thì không đưa
biến không đạt đến được trước. Khi đó, tập các ký hiệu đạt đến được gồm S, vào R’.
a, b, A và B. Vậy không có ký hiệu không đạt đến được, nên không thực hiện Ví dụ 5.19. Loại bỏ các luật sinh- trong văn phạm G sau:
loại bỏ. Sau đó, xác định được A là ký hiệu vô sinh. Loại bỏ A cùng các luật
S → AB
sinh chứa nó thì dẫn đến văn phạm còn lại sẽ xuất hiện B là ký hiệu không đạt
đến được. A → aAB | 
B → bAB | 
5.5.2 Loại bỏ luật sinh-
Xác định các biến triệt tiêu được. A và B là các biến triệt tiêu được vì có
Trong mục này chúng ta sẽ chỉ ra rằng, nếu một ngôn ngữ phi ngữ cảnh các luật sinh A →  và B → . S cũng là biến triệt tiêu được vì có luật sinh S
không chứa xâu rỗng  thì tồn tại văn phạm sản sinh ra ngôn ngữ không → AB. Như thế, tập các biến triệt tiêu được gồm: {S, A, B}.
chứa các luật sinh-, tức là các luật sinh có vế phải là . Nghĩa là, chúng ta
có thể loại bỏ các luật sinh- trong văn phạm phi ngữ cảnh sinh ra ngôn Bây giờ xây dựng các luật sinh R’, trước hết xét luật sinh S → AB,
ngữ không chứa . Để thực hiện điều này, chúng bắt đầu bởi khái niệm chúng ta có các luật sinh mới trong R’:
S → AB | A | B
*
biến triệt tiêu được. Biến A được gọi là triệt tiêu được, nếu A ⇒ 
Cho văn phạm phi ngữ cảnh G = (N, , R, S), tập các biến triệt tiêu Xét luật sinh A → aAB, chúng ta có các luật sinh mới trong R’:
được, được ký hiệu Nt, trong G được xác định bởi các bước sau: A → aAB | aA | aB | a
1. Với mọi luật sinh A →  trong G thì A là biến triệt tiêu được, thêm Xét luật sinh B → bAB, chúng ta có các luật sinh mới trong R’:
A vào Nt.
B → bAB | bA | bB | b
2. Nếu có luật sinh B → C1C2…Cn trong G và C1, C2, …Cn  Nt thì B
Cuối cùng, chúng ta có văn phạm mới sau khi đã loại bỏ các luật sinh- như
là biến triệt tiêu được, thêm B vào Nt. Lặp lại bước này cho đến khi
sau:
không còn biến nào được thêm vào trong Nt.
S → AB | A | B
Bây giờ, chúng ta sẽ thực hiện việc loại bỏ các luật sinh- trong văn
phạm phi ngữ cảnh. Cho văn phạm phi ngữ cảnh G = (N, , R, S). Xác A → aAB | aA | aB | a
định tập các biến triệt tiêu được Nt trong G. Chúng ta xây dựng văn phạm phi B → bAB | bA | bB | b
ngữ cảnh G’ = (N, , R’, S) từ G, trong đó tập các luật sinh R’ được xác
định như sau: Bây giờ, chúng ta cần chứng minh rằng văn phạm sau khi loại bỏ các luật
sinh- bằng cách xây dựng như trên không làm thay đổi ngôn ngữ, ngoại
trừ xâu rỗng  không còn tồn tại trong ngôn ngữ.

109 110
Định lý 5.5. Nếu G’ là văn phạm được xây dựng từ văn phạm phi ngữ Bước quy nạp: Giả sử dẫn xuất có độ dài là n > 1, vậy có
cảnh G bởi cách loại bỏ luật sinh- ở trên thì L(G’) = L(G) - {}. 
A⇒X X X ⇒ w . Theo cách xây dựng G’, trong G phải có luật sinh
k
Chứng minh: Chúng ta cần chỉ ra rằng nếu w   thì w  L(G’) khi và
1 2
G' G'

chỉ khi w  L(G). Trong trường hợp tổng quát hơn, chúng ta chứng minh A →  mà X1X2…Xk nhận được từ  bằng cách thay thế các biến triệt tiêu
được. Nghĩa là, chúng ta có: A ⇒  ⇒ X 1 X 2 X k trong G. Ngoài ra, từ
G G
rằng:  

A ⇒ w khi và chỉ khi A ⇒ w , với w  *, w  , A  N. dẫn xuất A ⇒ X 1X 2 X k ⇒ w trong G’ ta có thể chia w thành w1w2…wk,
G' G'
G' G

  sao cho X ⇒ w (i = 1, 2, …, k) với số bước nhỏ hơn n. Theo giả thiết
Điều kiện cần: Giả sử A ⇒ w và w   cần chứng minh A ⇒ w i G' i
G G' 
quy nạp, thì trong G cũng có X ⇒w Vậy ta có
Bước cơ sở: Dẫn xuất chỉ một bước, nghĩa là có luật sinh A → w trong i G i

A⇒ ⇒ XX X ⇒ ww w ⇒ w trong G.
G thì cũng có luật sinh A → w trong G’ vì w  . Vậy A ⇒ w G G
1 2 k 1 2 k
G'
 
Bước quy nạp: Giả sử dẫn xuất có độ dài là n > 1, vậy có Vậy chúng ta đã chứng minh xong: A ⇒ w khi và chỉ khi A ⇒ w , với
 G' G
A⇒XX X ⇒ w . Chúng ta có thể chia w thành w1w2…wk, sao cho
G 1 2 k
G w  *, w  , A  N. Bằng cách thay A bởi S, chúng ta nhận được:
  
X i ⇒ w i (i = 1, 2, …, k) với số bước nhỏ hơn n. Nếu wi   thì theo giả S ⇒ w khi và chỉ khi S ⇒ w , với w  . Hay L(G’) = L(G) - {}.
G G' G

thiết quy nạp, chúng ta có X ⇒ w trong G’. Nếu wi =  thì Xi là biến triệt 5.5.3 Loại bỏ luật sinh đơn vị
i G' i

tiêu được. Như thế, trong G’ phải có luật sinh A → Y1Y2…Yk mà trong đó Yi = Các luật sinh có dạng A → B trong đó A và B là các biến được gọi là
 khi wi =  và Yi = Xi khi wi  . Hơn nữa, w   nên không thể mọi Yi đều các luật sinh đơn vị. Các luật sinh đơn vị thường gây khó khăn trong một
bằng . Vậy trong G’ có dẫn xuất: số các chứng minh và đặc biệt là tạo ra nhiều bước dẫn xuất không cần
thiết.
*
A ⇒ Y 1 Y2 Y k ⇒ X 1 X 2 X k ⇒ w 1 w 2 w k ⇒ w Cho G = (N, , R, S), xây dựng G’ = (N, , R’, S) không chứa các luật
G G G G
sinh đơn vị từ G:
 
Điều kiện đủ: Giả sử A ⇒ w cần chứng minh A ⇒ w 1. Đưa vào R’ các luật sinh không đơn vị của R.
G' G
*
Chúng ta dễ dàng nhận thấy w   vì G’ không chứa luật sinh-. Chúng 2. Xác định các cặp biến (A, B) mà A ⇒ B chỉ sử dụng các luật sinh

ta sẽ chứng minh bằng quy nạp trên độ dài của dẫn xuất A ⇒ w đơn vị. Để xác định các cặp (A, B), ta thực hiện các bước lặp:
G
*
a. (A, A) là cặp cần xác định với mọi biến A, vì A ⇒ A bởi
Bước cơ sở: Dẫn xuất chỉ gồm một bước, nghĩa là có luật sinh A → w
0 bước.
trong G’. Cách xây dựng G’ cho chúng ta biết rằng tồn tại A →  trong G,
với  là w khi thay thế không hoặc nhiều biến triệt tiêu được trong . Thế *
b. Nếu (A, B) là cặp thỏa mãn A ⇒ B và B → C là luật sinh,
 
thì trong G có A ⇒  ⇒ w , trong đó  ⇒ w là bước thay thế các biến triệt với C là biến thì (A, C) là cặp thỏa mãn A ⇒ C
*
G G G
tiêu được trong  bởi .

111 112
3. Đối với mỗi cặp biến (A, B) được xác định ở trên, thêm vào R’ các *
Giả sử S ⇒ w , theo cách xây dựng G’, thì mỗi luật sinh trong G’ tương
luật sinh A →  trong đó B →  là luật sinh không đơn vị trong R. G'

ứng với một dãy từ không hoặc nhiều luật sinh đơn vị và theo sau bởi một
Ví dụ 5.20. Loại bỏ luật sinh đơn vị của văn phạm G có tập các luật sinh *
R như sau: luật sinh không đơn vị trong G, nghĩa là  ⇒  tương ứng với  ⇒ 
G' G

S → aA | A *
Khi đó, thay thế các dẫn xuất trong S ⇒ w bởi các dẫn xuất tương ứng
G'
A→B|a *

B → A | ab | bb trong G thì ta có S ⇒ w , vậy w  L(G).


G

Xây dựng tập luật sinh R’ bằng cách loại bỏ các luật sinh đơn vị Điều kiện đủ: Giả sử w  L(G) cần chứng minh w  L(G’).
trong R. Đặt các luật sinh không đơn vị của R vào trong R’. *
Khi đó tồn tại dẫn xuất trái nhất trong G sinh xâu w: S ⇒ w . Nếu trong
S → aA G

dẫn xuất này có xuất hiện luật sinh đơn vị thì biến vế bên phải của luật
A→a
sinh đơn vị này lại tiếp tục được thay thế trong dẫn xuất. Chúng ta có thể
B → ab | bb chia dẫn xuất trái nhất này thành dãy các bước, mà mỗi bước là không
* * * * hoặc nhiều luật sinh đơn vị được theo sau bởi luật sinh không đơn vị. Theo
Chúng ta có các dẫn xuất sau: S ⇒ A , S ⇒ B , A ⇒ B , B ⇒ A . Thực cách xây dựng G’, thì mỗi bước này chính là một luật sinh trong G’. Vậy
hiện lần lượt thay thế vế phải của các dẫn xuất này, ta có: *
S ⇒ w hay w  L(G’).
S → a | ab | bb G'

A → ab | bb 5.5.4 Giản lược văn phạm phi ngữ cảnh


B→a Ở trên, chúng ta vừa thực hiện một số bước giản lược một văn phạm phi
Vậy cuối cùng chúng ta có các luật sinh trong R’ như sau: ngữ cảnh G thành G’ tương đương sao cho G’ không chứa các biến vô ích,
các luật sinh- và các luật sinh đơn vị. Việc xây dựng G’ từ G phải được
S → aA | a | ab | bb
thực hiện theo đúng thứ tự sau:
A → a | ab | bb
1. Loại bỏ các luật sinh-.
B → a | ab | bb
2. Loại bỏ các luật sinh đơn vị.
Bây giờ chúng ta cần chỉ ra rằng việc loại bỏ các luật sinh đơn vị trong
3. Loại bỏ các biến vô ích.
một văn phạm phi ngữ cảnh không làm ảnh hưởng đến ngôn ngữ được sinh
ra bởi văn phạm. Định lý 5.7. Cho L là ngôn ngữ phi ngữ cảnh không chứa  thì tồn tại một
văn phạm phi ngữ cảnh sản sinh ra L không chứa các biến vô ích, các luật
Định lý 5.6. Nếu G’ là văn phạm được xây dựng từ văn phạm G bởi
sinh- và các luật sinh đơn vị.
thuật toán loại bỏ các luật sinh đơn vị mô tả ở trên, thì L(G’) = L(G).
Định lý này thực ra là kết quả từ các định lý 5.4, 5.5 và 5.6 đã được
Chứng minh: Chúng ta chỉ ra rằng w  L(G) khi và chỉ khi w  L(G’).
chứng minh trong các phần trước.
Điều kiện cần: Giả sử w  L(G’) cần chứng minh w  L(G).

113 114
5.5.5 Dạng chuẩn Chomsky A → a | bbc
Định nghĩa 5.6. Một văn phạm là thuộc dạng chuẩn Chomsky B → b | Ac
(Chomsky Normal Form) nếu mọi luật sinh của nó có một trong hai dạng đơn Xây dựng G’ ở dạng chuẩn Chomsky tương đương G như sau:
giản sau:
Các luật sinh sau trong G thỏa mãn dạng chuẩn Chomsky được đưa
1. A → a, trong đó A là biến, a là ký hiệu kết thúc. vào G’:
2. A → BC, trong đó A, B, C là các biến. S→a
Cho văn phạm phi ngữ cảnh G = (N, , R, S) với L(G) không rỗng và
A→a
không chứa . Không mất tính tổng quát, chúng ta giả sử văn phạm G
không chứa các biến vô ích, các luật sinh- và các luật sinh đơn vị (nhờ B→b
vào định lý 5.5). Chúng ta xây dựng văn phạm G’ = (N’, , R’, S) tương Thêm vào các biến đại diện mới Vb và Vc và thay thế các ký hiệu kết thúc
đương ở dạng chuẩn Chomsky từ văn phạm G như sau: trong các luật sinh còn lại bởi các biến đại diện mới.
1. Đặt các luật sinh dạng A → a vào R’ (vì đã thỏa mãn dạng chuẩn). S → ABVb
2. Đối với các luật sinh dạng A → x1x2…xn với n  2, xi  (N  ), A → VbVbVc
i = 1, 2, … n, nếu xi là một ký hiệu kết thúc, chẳng hạn xi = a,
a  , thì thay thế xi bởi một biến đại diện mới Bi. Khi đó luật sinh B → AVc
A → x1x2…xn sẽ có dạng A → B1B2…Bn. Các biến đại diện Bi mới Vb → b
được thêm vào N’. Ứng với mỗi biến Bi, chúng ta thêm vào R’ luật
Vc → c
sinh Bi → a.
Các luật sinh sau đã thỏa mãn dạng chuẩn Chomsky nên được đưa
3. Sau khi thực hiện xong bước 2, ứng với mỗi luật sinh vào G’:
A → B1B2…Bn mà n = 2 thì chúng ta đặt nó vào R’ (vì đã thỏa mãn
dạng chuẩn). Ngược lại, nếu n > 2 chúng ta thêm n - 2 các biến mới Vb → b
C1, C2, …Cn-2 vào N’ và đưa vào R’ các luật sinh sau: Vc → c
A → B1C1 B → AVc
C1 → B2C2 Thêm vào các biến mới C1 và C2 để biến đổi các luật sinh còn lại:
… S → ABVb
Cn-3 → Bn-2Cn-2 A → VbVbVc
Cn-2 → Bn-1Bn về dạng chuẩn Chomsky:
Như vậy, tất cả các luật sinh trong G’ sẽ thỏa mãn dạng chuẩn S → AC1
Chomsky.
C1 → BVb
Ví dụ 5.21. Biến đổi văn phạm phi ngữ cảnh G sau về dạng chuẩn
A → VbC2
Chomsky:
C2 → VbVc
S → a | ABb

115 116
Cuối cùng, chúng ta nhận được văn phạm G’ ở dạng chuẩn Chomsky Chứng minh tương tự, chúng ta có một dãy các dẫn xuất sinh ra w
như sau:
trong G1 tương ứng với một dẫn xuất sinh ra w trong G2.
S→a
A→a 5.6 Bài tập chương 5
Bài 5.1. Xây dựng văn phạm phi ngữ cảnh sinh các ngôn ngữ sau:
B→b
a. {0n11n | n > 0}
Vb → b
b. {0n12n | n ≥ 0}
Vc → c
c. {ancmbn | m, n ≥ 0}
B → AVc
d. {w  {0, 1}* | w = wR}
S → AC1
e. {w  {0, 1}* | w có số ký hiệu 0 bằng số ký hiệu 1}
C1 → BVb
f. {amcnbp | m +2n ≥ p}
A → VbC2
g. {ambncpdq | m + n = p + q}
C2 → VbVc
Bài 5.2. Cho văn phạm phi ngữ cảnh G = ({S, A, B}, {a, b}, R, S), trong đó
Định lý 5.8. Mọi văn phạm phi ngữ cảnh G mà L(G) chứa ít nhất một R gồm các luật sinh sau:
xâu khác  thì tồn tại văn phạm G1 ở dạng chuẩn Chomsky sao cho
S → ABA
L(G1) = L(G) - {}.
A → a | bb
Chứng minh: Theo định lý 5.5 thì chúng ta hoàn toàn có thể xây dựng văn
phạm G2 = L(G) - {} không chứa các biến vô ích, các luật sinh- và các luật B → bS | 
sinh đơn vị. Bây giờ chúng ta cần chỉ ra L(G2) = L(G1). Hãy xác định ngôn ngữ L(G).
Chứng minh L(G2)  L(G1). Bài 5.3. Hãy chứng minh rằng văn phạm dưới đây là nhập nhằng:
Nếu dẫn xuất ra w sử dụng một luật sinh trong G2, giả sử là X S → A1B
→ X1X2…Xn thì ta dễ dàng chỉ ra rằng một dãy các luật sinh trong G1 được
sử dụng theo cách mà chúng ta vừa xây dựng G1 ở trên. Nghĩa là, một dẫn A → 0A | 
xuất trong G2 ứng với một dãy các dẫn xuất trong G1. Trước hết, nếu Xi là B → 0B | 1B | 
một ký hiệu kết thúc, thì trong G1 có một biến tương ứng Bi và một luật sinh
Bài 5.4. Cho văn phạm phi ngữ cảnh sau:
Bi → Xi. Nếu k = 2 thì đó chính cũng là luật sinh trong G1. Nếu k > 2, thì
trong G1 sẽ có các luật sinh A → B1C1, C1 → B2C2, … trong đó Bi là biến đại S → aS | aSbS | 
diện của ký hiệu kết thúc Xi hoặc chính là biến Xi. Dãy các dẫn xuất này a. Hãy chỉ ra rằng văn phạm trên là nhập nhằng.
trong G1 tương ứng với dẫn xuất sử dụng luật sinh X → X1X2…Xn trong
G2. Như thế, trong G1 cũng có dẫn xuất tương ứng với luật sinh X → b. Tìm một văn phạm phi ngữ cảnh không nhập nhằng tương
X1X2…Xn trong G2. Vậy, w thuộc L(G1). đương.

Chứng minh L(G1)  L(G2). Bài 5.5. Cho văn phạm phi ngữ cảnh sau:
S → AaSbB | 

117 118
A → aA | a Chương 6. Ô-tô-mát đẩy xuống
B → bB | 
a. Hãy chỉ ra rằng văn phạm trên là nhập nhằng.
b. Hãy loại bỏ sự nhập nhằng của văn phạm trên.
Như chúng ta đã biết, ô-tô-mát hữu hạn chỉ có thể nhận biết được lớp các
Bài 5.6. Loại bỏ các ký hiệu vô ích trong văn phạm sau:
ngôn ngữ chính quy. Trong chương này, chúng ta sẽ tìm hiểu một loại
S → BC | BA | a ô-tô-mát, được gọi là ô-tô-mát đẩy xuống, cho phép nhận biết các ngôn ngữ
B → Bb | BC phi ngữ cảnh. Ô-tô-mát đẩy xuống là một sự mở rộng của ô-tô-mát hữu hạn
với việc sử dụng thêm một bộ nhớ dạng ngăn xếp.
A→a
C → Bb | c 6.1 Ô-tô-mát đẩy xuống
Bài 5.7. Cho văn phạm phi ngữ cảnh 6.1.1 Mô tả không hình thức
S → aAa | bBb |  Về cơ bản một ô-tô-mát đẩy xuống (PushDown Automata) là một ô-tô-
A→C|a mát hữu hạn không đơn định với một bộ nhớ vô hạn hoạt động theo cơ chế
ngăn xếp. Bộ nhớ này cho phép ô-tô-mát đẩy xuống ghi nhớ một lượng
B→C|b thông tin vô hạn. Ô-tô-mát đẩy xuống được minh họa bởi hình 6.1.
C → CDE | 
0 0 1 1 0 1 0 1 1 1 0
D → A | B | ab
a. Giản lược văn phạm. Đầu đọc Băng vào
b. Chuyển văn phạm về dạng chuẩn Chomsky.
Bài 5.8. Chuyển văn phạm phi ngữ cảnh dưới đây về dạng chuẩn q Bộ điều khiển
Chomsky:
S → SaB | aB
Ngăn xếp
B → bB | 
Bài 5.9. Chuyển văn phạm phi ngữ cảnh dưới đây về dạng chuẩn Hình 6.1. Minh họa ô-tô-mát đẩy xuống
Chomsky: Như thế, sự khác nhau cơ bản giữa ô-tô-mát đẩy xuống và ô-tô-mát hữu
F→I|(E) hạn không đơn định là bộ nhớ ngăn xếp. Ngăn xếp hoạt động theo cơ chế vào
sau ra trước (Last In First Out), nghĩa là khi đưa ký hiệu vào nó sẽ nằm ở
T→F|T*F
đỉnh ngăn xếp, khi lấy ra thì lấy ký hiệu nằm ở đỉnh ngăn xếp.
E→T|E+T
Cũng như ô-tô-mát hữu hạn, ô-tô-mát đẩy xuống đọc xâu vào trên băng
I → a | b | aI | bI vào, mỗi ký hiệu tại một thời điểm, đọc ký hiệu trên đỉnh ngăn xếp và dịch
chuyển của ô-tô-mát sẽ dựa trên trạng thái hiện tại, ký hiệu đầu đọc đang

119 120
đọc và ký hiệu trên đỉnh ngăn xếp. Mỗi bước dịch chuyển ô-tô-mát đẩy - z   là ký hiệu đầu tiên trên đỉnh ngăn xếp,
xuống thực hiện: - F  Q là tập hữu hạn các trạng thái cuối,
- Đọc một ký hiệu trên băng vào, nếu là ký hiệu rỗng  thì không -  là hàm dịch chuyển được định nghĩa như sau:
ký hiệu nào được đọc.
: Q x (  {}) x  → tập con hữu hạn của Q x *.
- Chuyển sang trạng thái mới, tuy nhiên có thể ở lại cùng trạng
thái trước đó. Như thế, một dịch chuyển có thể được viết: (q, u, X) = {(p, )}, trong
đó:
- Thay thế ký hiệu trên đỉnh ngăn xếp bởi một xâu ký hiệu. Có
các khả năng dưới đây xảy ra: - q là trạng thái trong Q,

o Nếu xâu ký hiệu là  thì tương ứng việc lấy ký hiệu trên - u là ký hiệu vào trong  hoặc xâu rỗng ,
đỉnh ngăn xếp. - X thuộc  là ký hiệu trên đỉnh ngăn xếp
o Nếu xâu ký hiệu chính là ký hiệu trên đỉnh ngăn xếp thì - p là trạng thái mới,
đỉnh ngăn xếp được giữ nguyên.
-  là chuỗi ký hiệu thay thế X ở trên đỉnh ngăn xếp. Lưu ý, có
o Thay thế ký hiệu trên đỉnh ngăn xếp bởi một ký hiệu các khả năng của  như sau:
khác.
o Nếu  =  thì ký hiệu trên đỉnh ngăn xếp bị lấy ra, nghĩa
o Thay thế ký hiệu trên đỉnh ngăn xếp bởi hai hay nhiều là lấy X.
các ký hiệu.
o Nếu  = X thì ngăn xếp không thay đổi.
Có hai cách để ô-tô-mát đẩy xuống thừa nhận xâu vào:
o Nếu  = YZ thì X được thay thế bởi Z và Y được đẩy vào
- Xâu vào được đọc xong và ô-tô-mát ở trong một trong các trạng ngăn xếp.
thái cuối.
Ví dụ 6.1. Xây dựng ODX đoán nhận ngôn ngữ L = {anbn | n  0}.
- Xâu vào được đọc xong và ngăn xếp rỗng.
Chúng ta xây dựng ODX với ý tưởng như sau:
6.1.2 Định nghĩa hình thức - Khi đọc một ký hiệu a, chúng ta ghi nhớ việc đã đọc một ký
Định nghĩa 5.1. Một ô-tô-mát đẩy xuống M, được ký hiệu ODX, là hiệu a vào ngăn xếp, giả sử ghi vào ngăn xếp ký hiệu 1.
một bộ bảy: - Khi đọc ký hiệu b đầu tiên, thì chuyển sang trạng thái đọc ký
M = (Q, , , , q0, z, F), hiệu b và xóa một ký hiệu 1 ra khỏi ngăn xếp, nghĩa là vừa đọc
ký hiệu b tương ứng với ký hiệu a.
trong đó:
- Tiếp tục đọc ký hiệu b và xóa ký hiệu 1 trên đỉnh ngăn xếp cho
- Q là tập hữu hạn các trạng thái, đến khi hết xâu vào, nếu ngăn xếp rỗng thì đoán nhận xâu vào
-  là bảng chữ vào, (vì số ký hiệu b vừa đọc bằng số ký hiệu a đã được đọc trước
-  là tập các ký hiệu sử dụng trên ngăn xếp hay còn gọi là bộ đó).
chữ ngăn xếp, Với ý tưởng trên, chúng ta sẽ sử dụng ba trạng thái: q0 thực hiện đọc ký
hiệu a, q1 thực hiện đọc ký hiệu b và trạng thái đoán nhận q2.
- q0  Q là trạng thái đầu,
Như thế, chúng ta xây dựng ODX M gồm các thành phần như sau:
121 122
Q = {q0, q1, q2}, 4. Các trạng thái không thuộc F là các nút được biểu diễn bởi chỉ một
 = {a, b}, vòng tròn.

 = {z, 1}, 5. Các cung tương ứng với các dịch chuyển. Một cung từ trạng thái q
đến trạng thái p được gán nhãn a, X /  nghĩa là (q, a, X) chứa
q0  Q là trạng thái đầu (p, ). Như thế, một cung sẽ cho chúng ta biết ký hiệu vào được
z là ký hiệu đầu tiên trên đỉnh ngăn xếp, đọc, các ký hiệu trên đỉnh ngăn xếp trước và sau khi thực hiện dịch
chuyển.
F = {q2},
Biểu đồ này không cho chúng ta biết ký hiệu đầu tiên trên đỉnh ngăn
 được định nghĩa bởi các dịch chuyển sau:
xếp, tuy nhiên thông thường chúng ta quy ước đó là ký hiệu z.
1. (q0, a, z) = {(q0, 1z)}. Khi đọc ký hiệu a đầu tiên ghi ký Ví dụ 6.2. Biểu diễn ODX trong ví dụ 6.1 bằng biểu đồ trong hình 6.2.
hiệu 1 vào ngăn xếp.
2. (q0, a, 1) = {(q0, 11)}. Khi đọc các ký hiệu a tiếp theo ghi a, z / 1z b, 1 / 
ký hiệu 1 vào ngăn xếp.
b, 1 /  , z / 
3. (q0, b, 1) = {(q1, )}. Khi đọc ký hiệu b đầu tiên xóa ký q0 q1 q2
hiệu 1 trên ngăn xếp và chuyển sang trạng thái q1, là trạng
thái dùng để đọc các ký hiệu b.
4. (q1, b, 1) = {(q1, )}. Khi đọc các ký hiệu b tiếp theo xóa a, 1 / 11 , z / 
ký hiệu 1 trên ngăn xếp.
Hình 6.2. ODX đoán nhận ngôn ngữ {anbn | n  0}
5. (q1, , z) = {(q2, )}. Khi đọc hết xâu và đồng thời ngăn xếp
chỉ còn chứa ký hiệu đầu (z), thì xóa ký hiệu đó trên ngăn 6.1.4 Cấu hình của ODX
xếp đồng thời chuyển sang thái cuối q2 để đoán nhận xâu
Định nghĩa 6.2. Cấu hình của một ODX là một bộ ba (q, w, ), trong
vào.
đó:
6. (q0, , z) = {(q2, )}. Trường hợp đặc biệt, khi xâu vào rỗng
- q là trạng thái hiện tại,
thì cũng cho phép đoán nhận.
- w là phần xâu vào sẽ đọc,
6.1.3 Biểu diễn ODX bằng biểu đồ -  là nội dung của ngăn xếp.
Việc biểu diễn ODX bằng danh sách các dịch chuyển là không dễ dàng để
Chúng ta quy ước, nội dung của ngăn xếp từ đỉnh đến đáy được biểu
theo dõi. Một cách trực quan hơn, chúng ta có thể sử dụng biểu đồ dịch
diễn bởi  từ trái qua phải.
chuyển biểu diễn một ODX:
Định nghĩa 6.3. Cho ODX M = (Q, , , , q0, z, F). Giả sử (q, a, X)
1. Các nút biểu diễn các trạng thái của ODX.
chứa (p, ). Khi đó, với mọi w trong * và  trong *, chúng ta định nghĩa
2. Có một mũi tên đi vào nút q0 để ký hiệu trạng thái đầu. dịch chuyển cấu hình, ký hiệu├, như sau:
3. Các trạng thái kết thúc F là các nút được biểu diễn bởi hai vòng (q, aw, X)├ (p, w, )
tròn.

123 124
Ngoài ra, chúng ta sử dụng ├* để định nghĩa dịch chuyển của từ không - Khi đọc mỗi ký hiệu của xâu wR chúng ta sẽ đối sánh với ký
đến nhiều cấu hình của ODX. hiệu được lấy trên đỉnh ngăn xếp.
Ví dụ 6.3. Chúng ta có các dịch chuyển cấu hình để đoán nhận xâu vào - Khi gặp ký hiệu đầu tiên trên đỉnh ngăn xếp z thì chuyển sang
w = aaabbb bởi ODX trong ví dụ 6.2 như sau: trạng thái đoán nhận.
(q0, aaabbb, z)├ (q0, aabbb, 1z)├ (q0, abbb, 11z)├ (q0, bbb, 111z)├ Như thế, chúng ta xây dựng ODX M gồm các thành phần như sau:
(q1, bb, 11z)├ (q1, b, 1z)├ (q1, , z)├ (q2, , ). Q = {q0, q1, q2},
6.2 Ngôn ngữ được đoán nhận bởi ODX  = {a, b},

Như chúng ta đã biết, một ODX đoán nhận xâu vào bởi một trong hai  = {z, a, b},
cách: q0  Q là trạng thái đầu
- Đoán nhận bởi trạng thái cuối: xâu vào được đọc xong và ô-tô- z là ký hiệu đầu tiên trên đỉnh ngăn xếp,
mát ở trong một trong các trạng thái cuối.
F = {q2},
- Đoán nhận bởi ngăn xếp rỗng: xâu vào được đọc xong và ngăn
 được định nghĩa bởi các dịch chuyển sau:
xếp rỗng.
Thực ra thì hai cách đoán nhận này là tương đương với nhau. Nghĩa là, 1. (q0, a, z) = {(q0, az)} và (q0, b, z) = {(q0, bz)}. Khi đọc ký
nếu ngôn ngữ L có một ODX đoán nhận nó bởi trạng thái cuối khi và chỉ khi hiệu đầu tiên của xâu w ghi nó vào ngăn xếp.
L cũng có một ODX đoán nhận nó bởi ngăn xếp rỗng. Trong mục này, chúng 2. (q0, a, a) = {(q0, aa)}, (q0, a, b) = {(q0, ab)}, (q0, b, a) =
ta sẽ chỉ ra làm thế nào để chuyển một ODX đoán nhận L bởi trạng thái cuối {(q0, ba)} và (q0, b, b) = {(q0, bb)}. Khi đọc các ký hiệu tiếp
thành ODX đoán nhận L bởi ngăn xếp rỗng và ngược lại. theo của xâu w thì ghi vào ngăn xếp. Lưu ý, chúng ta có bốn
khả năng khác nhau: đọc ký hiệu a, trên đỉnh ngăn xếp là ký
6.2.1 Đoán nhận bởi trạng thái cuối hiệu a hoặc b; đọc ký hiệu b, trên đỉnh ngăn xếp là ký hiệu a
Định nghĩa 6.4. Cho ODX M = (Q, , , , q0, z, F). Gọi L(M) là ngôn hoặc b.
ngữ được đoán nhận bởi trạng thái cuối: 3. (q0, , a) = {(q1, a)} và (q0, , b) = {(q1, b)}. Chuyển từ
L(M) = {w | (q0, w, z) ├* (qf, , )} trạng thái q0 sang q1 để đọc xâu wR mà không đọc gì cả (nghĩa
là đọc ) và giữ nguyên nội dung ngăn xếp.
trong đó, qf  F và   *.
4. (q1, a, a) = {(q1, )} và (q1, b, b) = {(q1, )}. Khi đọc một
Nghĩa là, xuất phát từ cấu hình đầu, ODX đọc hết xâu vào w và chuyển ký hiệu của xâu wR thì lấy ký hiệu trên đỉnh ngăn xếp ra đối
sang một trạng thái cuối. Nội dung của ngăn xếp ở thời điểm đoán nhận là sánh, nếu trùng khớp thì lấy ký hiệu đó ra khỏi ngăn xếp.
không quan trọng.
5. (q1, , z) = {(q2, z)}. Khi đọc xong xâu vào mà gặp ký hiệu z
Ví dụ 6.4. Xây dựng ODX đoán nhận ngôn ngữ sau bởi trạng thái cuối:
trên đỉnh ngăn xếp thì khi đó xâu vào có dạng wwR. Vậy
L = {wwR | w  {a, b}*}. chúng ta chuyển sang trạng thái đoán nhận q2.
Chúng ta sẽ xây dựng ODX như sau: 6. (q0, , z) = {(q2, z)}. Trường hợp đặc biệt, đoán nhận xâu
- Khi đọc các ký hiệu của xâu w chúng ta sẽ ghi nhớ vào ngăn vào rỗng.
xếp.

125 126
Một cách trực quan, chúng ta biểu diễn ODX trên bằng biểu đồ dịch 6.2.3 Chuyển từ ODX đoán nhận bởi ngăn xếp rỗng thành
chuyển trong hình 6.3. ODX đoán nhận bởi trạng thái cuối
a, z / az Định lý 6.1. Nếu L = N(M) với một ODX đoán nhận bởi ngăn xếp rỗng
b, z / bz M = (Q, , , , q0, z), thì tồn tại ODX đoán nhận bởi trạng thái cuối M’
a, a / aa , z / z sao cho L = L(M’).
a, b / ab
b, a / ba a, a /  Chứng minh: Ý tưởng của việc chứng minh được minh họa trong
b, b / bb b, b /  hình 6.4. Chúng ta xây dựng M’ bắt chước các dịch chuyển của M và khi
M xóa hết ngăn xếp thì cho M’ chuyển về trạng thái cuối. Để thực hiện
điều đó, chúng ta sử dụng một ký hiệu mới z’ không thuộc . Ký hiệu z’
q0 q1 q2 được đặt ở đáy ngăn xếp của M’. Khi đó, nếu M’ nhìn thấy z’ ở trên đỉnh
, a / a , z / z của ngăn xếp nghĩa là M đã làm rỗng ngăn xếp trên cùng một xâu vào.
, b / b
, z’ / 
Hình 6.3. ODX đoán nhận ngôn ngữ {ww | w  {a, b} }
R *

6.2.2 Đoán nhận bởi ngăn xếp rỗng


Định nghĩa 6.5. Cho ODX M = (Q, , , , q0, z, F). Gọi N(M) là ngôn , z’ / 
ngữ được đoán nhận bởi ngăn xếp rỗng:
, z’ / zz’
N(M) = {w | (q0, w, z) ├* (q, , )}, , z’ /  qf
q0’ q0 M
trong đó, q  Q.
Nghĩa là, xuất phát từ cấu hình đầu, ODX đọc hết xâu vào w và đồng , z’ / 
thời ngăn xếp rỗng. Trạng thái của ODX ở thời điểm đoán nhận là bất kỳ
(không nhất thiết phải là trạng thái cuối).
Ví dụ 6.5. Xây dựng ODX đoán nhận ngôn ngữ L bởi trạng thái cuối: Hình 6.4. M’ bắt chước M và đoán nhận khi M làm ngăn xếp rỗng

L = {wwR | w  {a, b}*}. Như thế, M’ được xây dựng từ M bởi việc thêm vào trạng thái đầu mới
q0’, thực hiện việc thêm ký hiệu z vào đỉnh ngăn xếp và chuyển sang trạng
ODX M được xây dựng tương tự như trong ví dụ 6.4. Tuy nhiên, dịch thái q0. Sau đó, M’ bắt chước các dịch chuyển của M. Cuối cùng, thêm vào
chuyển (q1, , z) = {(q2, z)} được thay thế bởi dịch chuyển (q1, , z) = M’ trạng thái cuối qf và đối với mỗi trạng thái q trong M, thêm vào dịch
{(q2, )}, nghĩa là khi đọc xong xâu thì chúng ta xóa ngăn xếp. Trong chuyển (q, , z’) chứa (qf, ) để chuyển sang trạng thái cuối khi ngăn xếp
trường hợp này thì q2 không cần thiết phải là trạng thái cuối, vì chúng ta rỗng.
thực hiện đoán nhận bởi ngăn xếp rỗng. Còn nếu q2 là trạng thái cuối thì
M’ gồm các thành phần được xây dựng từ M = (Q, , , , q0, z) như
ODX vừa đoán nhận bởi trạng thái cuối vừa đoán nhận bởi ngăn xếp rỗng.
sau:
Như thế, đối với ODX đoán nhận bởi ngăn xếp rỗng, tập các trạng thái
cuối là rỗng, nghĩa là có thể bỏ qua. Vậy chúng ta có thể mô tả ODX bởi chỉ M’ = (Q  {q0’, qf}, ,   {z’}, ’, q0’, z’, {qf}).
sáu thành phần (Q, , , , q0, z). Trong đó ’ được định nghĩa như sau:

127 128
1. ’(q0’, , z’) = {(q0, zz’)}.
2. Với mọi q trong Q, ký hiệu vào a trong   {} và X trong  thì o, z / zz
’(q, a, X) chứa mọi phần tử của (q, a, X). c, z / 

3. Với mọi q trong Q, ’(q, , z’) chứa (qf, ). , z’ / zz’ , z’ / 


q0’ q0 qf
Với cách xây dựng M’ như trên, chúng ta dễ dàng chỉ ra mọi xâu w
được M đoán nhận bởi ngăn xếp rỗng thì cũng được M’ đoán nhận bởi
trạng thái cuối. Hình 6.6. ODX đoán nhận bởi trạng thái cuối cho ví dụ 6.6
Thật vậy, quy tắc 1 cho phép M’ tiếp nhận cấu hình đầu của M. Hay mô tả một cách hình thức ODX trên ta có:
Quy tắc 2 cho phép M’ bắt chước mọi dịch chuyển của M’. Như thế, khi M’ = ({q0’, q0, qf}, {o, c}, {z, z’}, ’, q0’, z’, {qf})
đoán nhận xâu M xóa ngăn xếp rỗng, còn M’ xóa ngăn xếp còn lại một ký hiệu trong đó ’ được định nghĩa như sau:
là z’ ở đáy.
’(q0’, , z’) = {(q0, zz’)},
Quy tắc 3 cho phép M’ chuyển sang trạng thái cuối qf khi gặp lại z’ để
đoán nhận xâu vào. ’(q0, o, z) = {(q0, zz)},

Ví dụ 6.6. Chuyển ODX đoán nhận bởi ngăn xếp rỗng trong hình 6.5 ’(q0, c, z) = {(q0, )},
sang ODX đoán nhận bởi trạng thái cuối. ’(q0, , z’) = {(qf, )}.
o, z / zz
c, z /  6.2.4 Chuyển ODX đoán nhận bởi trạng thái cuối thành
ODX đoán nhận bởi ngăn xếp rỗng
Định lý 6.2. Nếu L = L(M) với một ODX đoán nhận bởi trạng thái cuối M =
q0 (Q, , , , q0, z, F), thì tồn tại ODX đoán nhận bởi ngăn xếp rỗng M’ sao cho
L = N(M’).
Hình 6.5. Ví dụ ODX đoán nhận bởi ngăn xếp rỗng
Chứng minh: Tương tự việc chứng minh định lý 6.1, chúng ta xây
Trong đó, o là đại diện cho ký hiệu “(” (dấu mở ngoặc), còn c đại diện cho dựng M’ bắt chước các dịch chuyển của M, nhưng khi M chuyển sang
ký hiệu “)” (dấu đóng ngoặc). trạng thái cuối thì M’ tiếp tục hoạt động để xóa ngăn xếp cho đến rỗng.
Mô tả một cách hình thức ODX trên, chúng ta có: Hình 6.7 minh họa việc xây dựng M’ từ M.

M = ({q0}, {o, c}, {z}, , q0, z) Như thế, M’ được xây dựng từ M bởi việc thêm vào trạng thái đầu mới q0’,
thực hiện việc thêm ký hiệu z vào đỉnh ngăn xếp và chuyển sang trạng thái q0.
trong đó  được định nghĩa như sau: Sau đó, M’ bắt chước các dịch chuyển của M. Cuối cùng, thêm vào M’ trạng
1. (q0, o, z) = {(q0, zz)}. Ghi ký hiệu z vào ngăn xếp nếu vừa đọc thái qe sao cho đối với mỗi trạng thái cuối qf trong M và ký hiệu X bất kỳ trên
dấu mở ngoặc. ngăn xếp chúng ta thêm vào dịch chuyển (qf, , X) chứa (qe, ), chuyển
sang trạng thái qe để thực hiện xóa ngăn xếp. Khi ở trạng thái qe, M’ thực
2. (q0, c, z) = {(q0, )}. Xóa ký hiệu z khỏi ngăn xếp nếu vừa đọc
hiện xóa ngăn xếp đến rỗng.
dấu đóng ngoặc.
Chúng ta chuyển thành ODX đoán nhận bởi trạng thái cuối trong
hình 6.6.
129 130
6.3 Sự tương đương giữa ODX và văn phạm phi
ngữ cảnh
, Xz’ /  Trong phần này chúng ta sẽ chỉ ra rằng ODX đoán nhận lớp các ngôn
ngữ phi ngữ cảnh.
, z’ / zz’ qe
q0’ q0 M 6.3.1 Chuyển văn phạm phi ngữ cảnh thành ODX
, Xz’ /  Giả sử G = (N, , R, S) là văn phạm phi ngữ cảnh sản sinh ngôn ngữ L.
Chúng ta sẽ xây dựng ODX M từ G bằng cách bắt chước các dẫn xuất trái
, Xz’ /  nhất trong G. Nghĩa là, chúng ta sẽ xây dựng M đoán nhận xâu w bắt
chước quá trình dẫn xuất trái nhất sinh ra w trong G.
Hình 6.7. M’ bắt chước M và đoán nhận khi M chuyển sang trạng thái Chúng ta gọi dạng câu trái nhất xA, trong đó x chỉ gồm các ký hiệu
cuối kết thúc ở bên trái của A, A là biến bên trái nhất,  là phần bên phải của A, 
có thể chứa ký hiệu kết thúc và biến. x được gọi là phần bên trái và A là
M’ gồm các thành phần được xây dựng từ M = (Q, , , , q0, z, F) như
phần bên phải của dạng câu trái nhất.
sau:
Ở mỗi bước dẫn xuất sinh xâu w, dạng câu trái nhất bị chia làm đôi tại
M’ = (Q  {q0’}, ,   {z’}, ’, q0’, z’)
biến bên trái nhất:
trong đó ’ được định nghĩa như sau:
- Phần bên phải A nằm ở trong ngăn xếp với A ở trên đỉnh ngăn
1. ’(q0’, , z’) = {(q0, zz’)}. xếp, lúc khởi đầu thì đó là ký hiệu S ở đỉnh ngăn xếp.
2. Với mọi q trong Q, ký hiệu vào a trong   {} và X trong  thì - Phần bên trái x chỉ gồm các ký hiệu kết thúc đã được đối sánh
’(q, a, X) chứa mọi phần tử của (q, a, X). với với phần đầu của xâu vào. Nghĩa là, xâu vào có dạng
3. Với mọi qf thuộc F và X thuộc   {z’} thì ’(qf, , X) chứa w = xy, y là phần còn lại trên băng vào.
(qe, ). Như thế, cấu hình của M là (q, y, A) biểu diễn dạng câu trái nhất xA.
4. Với mọi X thuộc   {z’} thì ’(qe, , X) chứa (qe, ). Bây giờ, một luật sinh sẽ được sử dụng để thay thế A, giả sử đó là A→ .
Khi đó, cấu hình mới của M là (q, y, ), trong trường hợp này M đọc xâu
Tương tự như chứng minh định lý 6.1, chúng ta cũng dễ dàng nhận thấy M’ rỗng . Lưu ý, M mà chúng ta đang xây dựng chỉ chứa duy nhất một trạng
được xây dựng như trên sẽ đoán nhận bởi ngăn xếp rỗng các xâu mà M đoán thái q.
nhận bởi trạng thái cuối.
Bây giờ, (q, y, ) có thể không biểu diễn dẫn xuất trái nhất, bởi vì 
Thật vậy, quy tắc 1 cho phép M’ tiếp nhận cấu hình đầu của M. có thể chứa các ký hiệu kết thúc. Nếu phần đầu của  chứa các ký hiệu
Quy tắc 2 cho phép M’ bắt chước mọi dịch chuyển của M. Như thế, khi kết thúc thì nó sẽ được so sánh với các ký hiệu M đọc tiếp theo của y và
đoán nhận xâu, M chuyển sang trạng thái cuối. xóa các ký hiệu kết thúc này ra khỏi ngăn xếp, cho đến khi gặp biến tiếp
theo thì chúng ta lại có dạng câu trái nhất. Chúng ta tiếp tục thực hiện các
Quy tắc 3 cho phép M’ chuyển từ trạng thái cuối qf của M sang trạng thái
bước trên. Với cách xây dựng M như trên, các ký hiệu trên ngăn xếp sẽ:
qe để xóa ngăn xếp.
- được thay thế bởi vế phải của luật sinh nếu đó là một biến, hoặc
Quy tắc 4 cho phép M’ xóa ngăn xếp cho đến rỗng và đoán nhận xâu
vào.

131 132
- được loại bỏ khỏi ngăn xếp sau khi đã so khớp với ký hiệu vào Quá trình đoán nhận xâu aaababab tương ứng trong M là:
tương ứng nếu đó là ký hiệu kết thúc. (q, aaababab, S)├ (q, aaababab, aAS)├ (q, aababab, AS)├ (q,
Khi ngăn xếp rỗng, ODX đoán nhận xâu vào bởi ngăn xếp rỗng. aababab, aAS)├ (q, ababab, AS)├ (q, ababab, abS)├ (q, abab, S)├ (q,
Ngoài ra, chúng ta nhận thấy rằng ở bước dịch chuyển đầu tiên thì luật abab, aA)├ (q, bab, A)├ (q, bab, bA)├ (q, ab, A)├ (q, ab, ab)├ (q, ,
sinh ứng với vế trái là biến đầu S sẽ được sử dụng, vì vậy S là ký hiệu đầu ).
trên đỉnh ngăn xếp (nghĩa là z = S). Định lý 6.3. Nếu G là một văn phạm phi ngữ cảnh, thì tồn tại ODX M
Như vậy, từ văn phạm G = (N, , R, S) chúng ta xây dựng M đoán nhận đoán nhận bởi ngăn xếp rỗng sao cho L(G) = N(M).
L(G) bởi ngăn xếp rỗng như sau: Chứng minh: Chúng ta xây dựng ODX M theo cách trình bày ở trên, và
M = ({q}, , N  , , q, S) cần chỉ ra rằng xâu w thuộc N(P) khi và chỉ khi w thuộc L(G).
trong đó  được định nghĩa như sau: Điều kiện cần: Giả sử w thuộc L(G). Như thế, tồn tại dẫn xuất trái nhất

1. Đối với mỗi biến A  N, thì: (q, , A) = {(q, ) | A →  là luật sinh S = 1 ⇒ 2 ⇒ … ⇒  n = w


trong G}. Dịch chuyển này nhằm thay thế A ở trên đỉnh ngăn xếp Chúng ta chứng minh bằng quy nạp theo i rằng (q, w, S) ├* (q, yi,i),
bởi  mà không đọc ký hiệu vào. trong đó yi và i là các thành phần của dạng câu trái nhất. Tức là, yi là
2. Đối với mỗi ký hiệu kết thúc a  , thì: (q, a, a) = {(q, )}. Dịch phần bên trái của dạng câu trái nhất, i là phần bên phải của dạng câu trái
chuyển này nhằm so khớp ký hiệu kết thúc trên đỉnh ngăn xếp với nhất.
ký hiệu M đang đọc trên băng vào và nếu trùng khớp thì xóa ký Bước cơ sở: Với i = 1, 1 = S. ODX M chưa thực hiện bước dịch
hiệu trên ngăn xếp. chuyển nào, nên y1 = w và 1 = S. Như thế, (q, w, S) ├* (q, w, S) luôn
Ví dụ 6.7. Chuyển văn phạm phi ngữ cảnh sau thành ODX tương ứng: đúng.

S → aAS | aA Bước quy nạp: Giả sử rằng chúng ta có (q, w, S) ├* (q, yi,i). Cần
chứng minh (q, w, S) ├* (q, yi+1,i+1). Bởi vì i là phần bên phải của dạng
A → aA | bA | ab câu trái nhất, nên nó bắt đầu bởi biến A. Bước dẫn xuất i ⇒ i+1 thực hiện
Chúng ta xây dựng ODX như sau: thay thế A bởi một trong các luật sinh có vế trái là A, giả sử đó là A → .
Theo cách xây dựng ODX M, luật (1) thay thế A trên đỉnh ngăn xếp bởi ,
M = ({q}, {a, b}, {S, A, a, b}, , q, S)
luật (2) cho phép so khớp ký hiệu kết thúc trên đỉnh ngăn xếp với ký hiệu
trong đó,  được định nghĩa như sau: M đang đọc trên băng vào. Như thế, M sẽ đạt đến cấu hình (q, yi+1,i+1),
(q, , S) = {(q, aAS), (q, aA)} biểu diễn dạng câu trái nhất i+1. Hơn nữa, chúng ta có n = w, nên n = .
Khi đó (q, w, S) ├* (q, , ), nghĩa là M đoán nhận w bởi ngăn xếp rỗng.
(q, , A) = {(q, aA), (q, bA), (q, ab)}
Điều kiện đủ: Chúng ta cần chỉ ra rằng với một biến A nếu
(q, a, a) = {(q, )} *
(q, x, A) ├* (q, , ), thì A ⇒ x. Chúng ta sẽ chứng minh bằng quy nạp
(q, b, b) = {(q, )}
theo số bước dịch chuyển của M.
Chẳng hạn, chúng ta sẽ xét dẫn xuất trái nhất trong G sinh ra xâu
Bước cơ sở: Chỉ có một dịch chuyển. Chỉ có một khả năng A →  là luật
aaababab:
sinh của G và luật sinh này được sử dụng bởi luật (1) khi xây dựng M. Trong
S ⇒ aAS ⇒ aaAS ⇒ aaabS ⇒ aaabaA ⇒ aaababA ⇒ aaababab. trường hợp này, x = , như thế chúng ta có A ⇒ .

133 134
Bước quy nạp: Giả sử M thực hiện n dịch chuyển, n > 1. Dịch chuyển 2. Thay đổi từ trạng thái p sang trang thái q khi ký hiệu X đã hoàn toàn
đầu tiên phải là luật (1), trong đó biến A được thay thế một trong các luật bị loại bỏ khỏi ngăn xếp.
sinh có vế trái là A trên đỉnh ngăn xếp. Giả sử luật sinh được sử dụng là A
Chúng ta biểu diễn một biến bởi ký hiệu [pXq]. Các bước xây dựng văn
→ X1X2…Xk, trong đó mỗi Xi là ký hiệu kết thúc hoặc biến.
phạm được chi tiết trong định lý dưới đây.
n − 1 dịch chuyển tiếp theo của M đọc xâu vào x và thực hiện loại bỏ
Định lý 6.4. Cho ODX M = (Q, , , , q0, Z) đoán nhận bởi ngăn xếp
các X1, X2, …, Xk ra khỏi ngăn xếp. Chúng ta có thể chia x thành x1x2…xk, rỗng. Thì tồn tại một văn phạm phi ngữ cảnh G sao cho L(G) = N(M).
trong đó xi là phần của xâu vào được đọc cho đến khi Xi được loại bỏ khỏi
ngăn xếp. Nghĩa là chúng ta có (q, xixi+1…xk, Xi) ├* (q, xi+1…xk, ) với Chứng minh: Chúng ta xây dựng G = (N, , R, S) từ M với tập biến N
mọi i = 1, 2, …, k. Hơn nữa, các chuỗi dịch chuyển này không thể nhiều gồm:
hơn n − 1 bước dịch chuyển. Như thế, đối với các Xi là biến, chúng ta áp 1. Một ký hiệu đặc biệt S là biến đầu.
*
dụng giả thuyết quy nạp, và chúng ta có Xi ⇒ xi. Trong trường hợp Xi là 2. Tất cả các biến khác có dạng [qXp], trong đó p và q là các trạng
một ký hiệu kết thúc, thì chỉ có một dịch chuyển được thực hiện nhằm so thái trong Q và X là ký hiệu trong ngăn xếp thuộc .
khớp Xi và xi, mà thực ra là giống nhau. Như thế, chúng ta cũng có
*
Tập các luật sinh R được xây dựng như sau:
Xi ⇒ xi.
1. Với mọi p  Q, R có luật sinh S → [q0Zp]. Ký hiệu [q0Zp]
Vậy chúng ta có dẫn xuất: nhằm sinh ra các xâu w mà khi M đoán nhận sẽ loại bỏ Z từ
* * * ngăn xếp trong khi chuyển từ trạng thái q0 sang trạng thái p.
A ⇒ X1X2…Xk ⇒ x1X2…Xk ⇒ … ⇒ x1x2…xk Nghĩa là (q0, w, Z) ├* (p, , ). Như thế, bắt đầu từ biến S, các
* luật sinh này sẽ sinh ra các xâu w mà M đoán nhận bởi ngăn
Nghĩa là, A ⇒ x. xếp rỗng.
Chúng ta cho A = S và x = w. Vì xâu w được đoán nhận bởi M, nên 2. Nếu (q, a, X) chứa (r, X1X2…Xk), trong đó: a    {},
chúng ta có (q, w, S) ├* (q, , ). Chúng vừa chứng minh bằng quy nạp ở X1, X2, …, Xk  , k  0, khi k = 0 thì X1X2…Xk = .
*
trên rằng S ⇒ w, nghĩa là w thuộc L(G). Thì với mọi r1, r2, …, rk  Q, R có luật sinh:
6.3.2 Chuyển ODX thành văn phạm phi ngữ cảnh [qXrk] → a[rX1r1][r1X2r2]…[rk-1Xkrk].
Trong mục này, chúng ta sẽ chỉ ra việc xây dựng văn phạm phi ngữ *
Bây giờ chúng ta cần chỉ ra rằng: [qXp] ⇒ w khi và chỉ khi
cảnh tương đương với một ODX. Văn phạm phi ngữ cảnh được xây dựng (q, w, X) ├* (p, , ).
mô phỏng việc ODX thay đổi trạng thái, loại bỏ ký hiệu trên đỉnh ngăn
xếp và đọc xâu vào. Giả sử cần loại bỏ khỏi ngăn xếp dãy ký hiệu Điều kiện cần: Giả sử có (q, w, X) ├* (p, , ), chúng ta chứng minh
*
X1X2…Xn và ODX bắt đầu bởi trạng thái p0 với X1 trên đỉnh ngăn xếp. Sau [qXp] ⇒ w bằng quy nạp theo số bước dịch chuyển được thực hiện bởi
khi thực hiện các dịch chuyển để loại bỏ X1 trên đỉnh ngăn xếp, ODX ở ODX.
trạng thái p1 và đã đọc phần xâu vào x1. ODX tiếp tục loại bỏ X2 trong khi
đọc phần xâu vào x2 và đạt đến trạng thái p2. Quá trình này tiếp tục cho Bước cơ sở: Chỉ có một bước dịch chuyển. Thì (p, ) phải thuộc
đến khi dãy ký hiệu X1X2…Xn bị loại bỏ khỏi ngăn xếp. Chúng ta sẽ xây (q, w, X) và w hoặc là một ký hiệu kết thúc hoặc là . Theo cách xây
dựng văn phạm phi ngữ cảnh, trong đó, mỗi biến biểu diễn sự kiện: dựng G, thì phải có luật sinh tương ứng [qXp] → w, như thế [qXp] ⇒ w.
1. Loại bỏ ký hiệu X trên đỉnh ngăn xếp. Bước quy nạp: Giả sử (q, w, X) ├* (p, , ) có n bước và n > 1. Dịch
chuyển này phải có bước đầu tiên:
135 136
(q, w, X) ├ (r0, x, X1X2…Xk)├* (p, , ) trong đó, rk = p. Theo cách xây dựng G, luật sinh này tương ứng việc
(r0, X1X2…Xk) thuộc (q, a, X).
trong đó, w = ax, a là ký hiệu kết thúc hoặc là . Khi đó, (r0, X1X2…Xk)
phải thuộc (q, a, X). Theo cách xây dựng G, chúng ta có luật sinh *
Chúng ta có thể chia w thành w = aw1w2…wk sao cho [ri-1Xiri] ⇒ wi với
[qXrk] → a[r0X1r1][r1X2r2]…[rk-1Xkrk] i = 1, 2, …, k. Áp dụng giả thuyết quy nạp, với mỗi i, chúng ta có:
trong đó, rk = p và r1, r2, …, rk  Q. (ri-1, wi, Xi)├* (ri, , )
Mỗi ký hiệu X1, X2, …, Xk sẽ lần lượt bị lấy ra khỏi ngăn xếp. Chúng ta có Vậy, chúng ta cũng có:
thể chọn ri là trạng thái của ODX khi Xi bị lấy ra khỏi ngăn xếp, với i = 1,
(ri-1, wiwi+1…wk, XiXi+1…Xk)├* (ri, wi+1…wk, Xi+1…Xk)
2, …, k. Giả sử x = w1w2…wn, trong đó wi là phần xâu vào được ODX đọc
khi Xi bị lấy ra khỏi ngăn xếp. Như thế, chúng ta có (ri-1, wi, Xi)├* (ri, Nếu chúng ta ghép các dịch chuyển này với nhau, chúng ta có:
, ). (q, aw1w2…wk, X)├ (r0, w1w2…wk, X1X2…Xk)├*
Bởi vì các dịch chuyển này đều có ít hơn n bước, áp dụng giả thuyết (r1, w2w3…wk, X2X3…Xk)├* (r2, w3…wk, X3…Xk)├*… ├* (rk, , )
*
quy nạp cho (ri-1, wi, Xi)├* (ri, , ), chúng ta có [ri-1Xiri] ⇒ wi. Kết hợp Bởi vì, rk = p, nên chúng ta có (q, w, X) ├* (p, , ).
các dẫn xuất này với luật sinh đầu tien, chúng ta có:
*
* Cuối cùng, chúng ta cần chỉ ra S ⇒ w khi và chỉ khi
[qXrk] → a[r0X1r1][r1X2r2]…[rk-1Xkrk] ⇒ (q0, w, Z) ├* (p, , ), bởi vì S là biến đầu. Thật vậy, chúng ta vừa chứng
* *
aw1[r1X2r2] [r2X3r3]…[rk-1Xkrk] ⇒ minh [q0Zp] ⇒ w khi và chỉ khi (q0, w, Z) ├* (p, , ). Mà theo cách xây
* dựng G, chúng ta có luật sinh S → [q0Zp]. Như thế, chúng ta vừa chứng
aw1w2[r2X3r3]…[rk-1Xkrk] ⇒ minh L(G) = N(M).
… Ví dụ 6.8. Chuyển ODX trong ví dụ 6.6 thành văn phạm phi ngữ cảnh
aw1w2 … wk = w tương đương.

trong đó, rk = p. ODX trong ví dụ 6.6 được định nghĩa:


* M = ({q0}, {o, c}, {z}, , q0, z)
Điều kiện đủ: Giả sử có [qXp] ⇒ w, chứng minh (q, w, X) ├* (p, , )
bằng quy nạp theo số bước dẫn xuất. trong đó  được định nghĩa như sau:

Bước cơ sở: Chỉ có một bước dẫn xuất, thì [qXp] → w phải là một luật (q0, o, z) = {(q0, zz)},
sinh. Như thế, theo cách xây dựng G, ODX phải có dịch chuyển từ trạng thái (q0, c, z) = {(q0, )}.
q sang trạng thái p trong khi X được lấy ra khỏi ngăn xếp. Nghĩa là, (p, )
Bởi vì, ODX này chỉ có một trạng thái duy nhất q0 và chỉ có một ký
phải thuộc (q, w, X). Như thế, chúng ta có dịch chuyển
hiệu trong ngăn xếp duy nhất z, nên việc xây dựng văn phạm phi ngữ
(q, w, X) ├ (p, , ).
cảnh G tương đương là rất đơn giản.
*
Bước quy nạp: Giả sử [qXp] ⇒ w thực hiện n bước, với n > 1. Dẫn xuất Văn phạm G có hai biến:
này phải có dạng: 1. S là biến đầu.
*
[qXrk] → a[r0X1r1][r1X2r2]…[rk-1Xkrk] ⇒ w

137 138
2. [q0zq0], bộ ba duy nhất được tạo nên từ các trạng thái và ký 1. Có các luật sinh:
hiệu ngăn xếp. a. S → [q0Zq0]
Văn phạm G có các luật sinh sau: b. S → [q0Zq1]
1. Luật sinh duy nhất cho S là: S → [q0zq0]. Trong trường hợp Xét biến [q0Zq0] đã xuất hiện bên vế phải luật sinh. 2. Vì (q0,
tổng quát nếu ODX có n trạng thái thì sẽ có n luật sinh loại
này. , Z) chứa (q0, ), vậy có luật sinh: [q0Zq0] → . 3. Vì (q0, a,

2. Vì (q0, o, z) chứa (q0, zz), vậy chúng ta có luật sinh Z) chứa (q1, AZ), vậy có các luật sinh:
[q0zq0] → o[q0zq0][q0zq0]. Trong trường hợp tổng quát nếu a. [q0Zq0] → a[q1Aq0][q0Zq0]
ODX có n trạng thái thì sẽ có n2 luật sinh loại này.
b. [q0Zq0] → a[q1Aq1][q1Zq0]
3. Vì (q0, c, z) chứa (q0, ), vậy có luật sinh: [q0zq0] → c.
Xét biến [q0Zq1] đã xuất hiện bên vế phải luật sinh.
Để đơn giản, đặt A = [q0zq0], chúng ta có văn phạm phi ngữ cảnh:
4. Vì (q0, a, Z) chứa (q1, AZ), vậy có các luật sinh:
S→A
a. [q0Zq1] → a[q1Aq0][q0Zq1]
A → oAA | c
b. [q0Zq1] → a[q1Aq1][q1Zq1]
Hay đơn giản hơn chúng ta có thể thay thế A bởi S, vì chúng cùng dẫn
Xét biến [q1Aq0] đã xuất hiện bên vế phải luật sinh. 5.
xuất ra cùng các xâu ký hiệu:
Vì (q1, b, A) chứa (q0, ), vậy có luật sinh:
S → oSS | c
[q1Aq0] → b
Ví dụ 6.9. Xây dựng văn phạm phi ngữ cảnh tương đương với ODX
M = ({q0, q1}, {a, b}, {A, Z}, , q0, Z), trong đó  được định nghĩa như Xét biến [q1Aq1] đã xuất hiện bên vế phải luật sinh. 6.
sau: Vì (q1, b, A) chứa (q0, ), vậy có luật sinh:
(q0, , Z) = {(q0, )} [q1Aq1] → b
(q0, a, Z) = {(q1, AZ)} Xét các biến [q1Zq0], [q1Zq1] và [q1Aq1] đã xuất hiện bên vế phải
(q1, b, A) = {(q0, )} của các luật sinh. Tuy nhiên, không thể có các dịch chuyển cho
phép xây dựng các luật sinh mà vế trái là các biến này, nghĩa là các
Xây dựng G = (N, {a, b}, R, S).
biến này vô ích. Vậy các biến này bị loại bỏ, điều này kéo theo các luật
N gồm các biến: { S, sinh 3.b, 4.b và 6 cũng bị loại bỏ.
[q0Aq0], [q0Aq1], [q1Aq0], [q1Aq1], Cuối cùng, còn lại các luật sinh trong G:
[q0Zq0], [q0Zq1], [q1Zq0], [q1Zq1]}. 1.a. S → [q0Zq0]
Tuy nhiên, chúng ta lưu ý rằng trong tập N có thể có các biến không đạt 1.b. S → [q0Zq1]
đến được. Vì vậy, chúng ta bắt đầu xây dựng các luật sinh có vế trái là S, sau
2. [q0Zq0] → 
đó chỉ xây dựng các luật sinh mà vế trái là biến đã xuất hiện trong vế phải của
một luật sinh đã được xây dựng trước đó. 3.a. [q0Zq0] → a[q1Aq0][q0Zq0]
Các luật sinh trong G được xây dựng như sau: 4.a [q0Zq1] → a[q1Aq0][q0Zq1]
139 140
5. [q1Aq0] → b tô-mát đẩy xuống đơn định tạo nên một lớp con các ngôn ngữ phi ngữ
Tuy nhiên, trong số các luật sinh trên chúng ta dễ dàng nhận thấy rằng cảnh, gọi là các ngôn ngữ phi ngữ cảnh đơn định.
biến [q0Zq1] là vô sinh, vậy loại bỏ nó cùng các luật sinh 1.b và 4.a chứa nó. Ví dụ 6.10. Ngôn ngữ {wwR | w  {a, b}} là ngôn ngữ phi ngữ cảnh
Vậy các luật sinh của G còn lại: không được thừa nhận bởi ô-tô-mát đẩy xuống đơn định. Tuy nhiên, nếu
chúng ta thêm một ký hiệu c ngăn cách hai xâu w và wR thì, ngôn ngữ
1.a. S → [q0Zq0]
{wcwR | w  {a, b}} sẽ được đoán nhận bởi ô-tô-mát đẩy xuống đơn định
2. [q0Zq0] →  (hình 6.8).
3.a. [q0Zq0] → a[q1Aq0][q0Zq0] a, z / az
5. [q1Aq0] → b b, z / bz
a, a / aa
Để đơn giản là thay [q0Zq0] bởi A, [q1Aq0] bởi B, cuối cùng chúng ta có
a, b / ab
văn phạm phi ngữ cảnh: b, a / ba a, a / 
b, b / 
S→A b, b / bb
A→
A → aBA q0 q1 q2
c, z / z , z / z
B→b c, a / a
c, b / b
6.4 Ô-tô-mát đẩy xuống đơn định
Hình 6.8. Ví dụ ô-tô-mát đẩy xuống đơn định
Chúng ta vừa được giới thiệu ô-tô-mát đẩy xuống không đơn định,
cũng như ô-tô-mát hữu hạn, chúng ta cũng có ô-tô-mát đẩy xuống đơn 6.5 Ngôn ngữ chính quy và ODX đơn định
định. Tuy nhiên, không như ô-tô-mát hữu hạn, ô-tô-mát đẩy xuống không
đơn định và ô-tô-mát đẩy xuống đơn định là không tương đương. Như đã trình bày ở trên, ODX đơn định chỉ đoán nhận lớp các ngôn
ngữ phi ngữ cảnh đơn định, chứ không thể đoán nhận lớp tất cả các ngôn
Một ô-tô-mát đẩy xuống là đơn định nếu nó không có sự lựa chọn trong ngữ phi ngữ cảnh. Tuy nhiên, trong mục này chúng ta sẽ chỉ ra rằng lớp
dịch chuyển của nó. các ngôn ngữ phi ngữ cảnh đơn định chứa lớp các ngôn ngữ chính quy.
Định nghĩa 6.6. Một ô-tô-mát đẩy xuống M = (Q, , , , q0, z, F) Định lý 6.5. Nếu L là ngôn ngữ chính quy thì tồn tại ODX đơn định M sao
được gọi là đơn định khi và chỉ khi các điều kiện sau được thỏa mãn: cho L = L(M).
1. (q, a, X) chứa nhiều nhất một phần tử, với q  Q, a    {}, Chứng minh: Chúng ta có thể xây dựng ODX đơn định phỏng theo
X  . một OHD. ODX có một ngăn xếp và thay đổi các ký hiệu trên đỉnh ngăn xếp
2. Nếu (q, a, X) là không rỗng, thì (q, , X) là phải rỗng, với a  . khi hoạt động. Tuy nhiên, ODX có thể bỏ qua ngăn xếp và chỉ sử dụng
Vấn đề đặt ra là mọi ngôn ngữ phi ngữ cảnh có được đoán nhận bởi ô- các trạng thái. Khi đó, ODX sẽ trở thành OHD.
tô-mát đẩy xuống đơn định không. Câu trả lời là không thể. Bởi vì tồn tại Giả sử tồn tại OHD N = (Q, ∑, N, q0, F) đoán nhận ngôn ngữ chính quy
những ngôn ngữ phi ngữ cảnh không được đoán nhận bởi ô-tô-mát đẩy L. Chúng ta xây dựng ODX đơn định M = (Q, ∑, {Z}, M, q0, Z, F), trong đó
xuống đơn định nào cả. Các ngôn ngữ phi ngữ cảnh được đoán nhận bởi ô- M được định nghĩa M(q, a, Z) = {(p, Z)} với q, p  Q và a  ∑ sao
cho N(q, a) = p.

141 142
Chúng ta dễ dàng chứng minh bằng quy nạp theo độ dài xâu w rằng - R = R1  R2  {S → S1S2}.
(q0, w, Z) ├* (p, , Z) khi và chỉ khi N*(q0, w) = p. Bởi vì cả ODX M và
OHD N đoán nhận xâu vào khi đạt đến trạng thái cuối, nên chúng ta khẳng 6.6.3 Tính đóng dưới phép bao đóng
định rằng chúng tương đương. Định lý 6.8. Nếu L ngôn ngữ phi ngữ cảnh thì L* cũng là ngôn ngữ phi ngữ
cảnh.
6.6 Các tính chất của ngôn ngữ phi ngữ cảnh
Chứng minh: Vì L ngôn ngữ phi ngữ cảnh nên tồn tại văn phạm phi ngữ
Trong mục này, chúng ta sẽ tìm hiểu một số các tính chất của ngôn ngữ phi cảnh G = (N, , R, S) sao cho L = L(G). Dễ dàng nhận thấy rằng ngôn ngữ L*
ngữ cảnh. Nhiều tính chất của ngôn ngữ phi ngữ cảnh tương tự như đối với = L(G’) với G’ = (N’, ’, R’, S’) là văn phạm phi ngữ cảnh được xây dựng
ngôn ngữ chính quy. Tuy nhiên, cũng có một số khác biệt. như sau:
6.6.1 Tính đóng dưới phép hợp - N’ = N,
Định lý 6.6. Nếu L1 và L2 là các ngôn ngữ phi ngữ cảnh thì L1  L2 - ’ = ,
cũng là ngôn ngữ phi ngữ cảnh. - S’ = S,
Chứng minh: Thật vậy, vì L1 và L2 là các ngôn ngữ phi ngữ cảnh nên tồn - R’ = R  {S → SS, S → }.
tại các văn phạm phi ngữ cảnh G1 = (N1, 1, R1, S1) và G2 = (N2, 2, R2, S2) sao
cho L1 = L(G1) và L2 = L(G2). Chúng ta dễ dàng nhận thấy rằng ngôn ngữ 6.6.4 Tính đóng dưới các phép toán khác
L1  L2 = L(G) với G = (N, , R, S) là văn phạm phi ngữ cảnh được xây dựng
Định lý 6.9. Nếu L ngôn ngữ phi ngữ cảnh thì LR cũng là ngôn ngữ phi ngữ
như sau:
cảnh.
- N = N1  N2  {S},
Chứng minh: Vì L ngôn ngữ phi ngữ cảnh nên tồn tại văn phạm phi
-  = 1  2, ngữ cảnh G = (N, , R, S) sao cho L = L(G). Chúng ta xây dựng
- S là biến đầu, GR = (N, , RR, S) mà RR là nghịch đảo các luật sinh của R, nghĩa là ứng với
mỗi luật sinh A →  trong R, sẽ xây dựng A → R trong RR. Dễ dàng nhận
- R = R1  R2  {S → S1, S → S2}. thấy rằng L(GR) = LR.
6.6.2 Tính đóng dưới phép ghép nối Định lý 6.10. Nếu L1 là ngôn ngữ phi ngữ cảnh và L2 là ngôn ngữ chính
quy thì L1  L2 là ngôn ngữ phi ngữ cảnh.
Định lý 6.7. Nếu L1 và L2 là các ngôn ngữ phi ngữ cảnh thì L1L2 cũng là
ngôn ngữ phi ngữ cảnh. Chứng minh: Cho M1 = (Q1, 1, 1, 1, q01, z1, F1) là ODX sao cho
L1 = L(M1) và M2 = (Q2, 2, 2, q02, F2) là OHD sao cho L2 = L(M2).
Chứng minh: Vì L1 và L2 là các ngôn ngữ phi ngữ cảnh nên tồn tại các
văn phạm phi ngữ cảnh G1 = (N1, 1, R1, S1) và G2 = (N2, 2, R2, S2) sao Chúng ta xây dựng ODX M đoán nhận L1  L2 mô phỏng hoạt động song
cho L1 = L(G1) và L2 = L(G2). Chúng ta dễ dàng nhận thấy rằng ngôn ngữ song của M1 và M2 và sử dụng ngăn xếp của M1: mỗi khi một ký hiệu từ
L1L2 = L(G) với G = (N, , R, S) là văn phạm phi ngữ cảnh được xây dựng chuỗi vào được đọc, M thực hiện đồng thời các dịch chuyển của M1 và M2.
như sau: M = (Q, , , , q0, z, F) có các thành phần được xây dựng như sau:
- N = N1  N2  {S}, - Q = Q1  Q 2
-  = 1  2, -  = 1  2
- S là biến đầu, -  = 1

143 144
- z = z1 Bài toán này có thể được giải quyết bởi một thủ tục hiệu quả. Thật vậy,
giả sử L được sản sinh bởi văn phạm phi ngữ cảnh G = (N, , R, S). Cần xác
- q0 = (q01, q02)
định xem S có là vô sinh không. Chúng ta dễ dàng nhận thấy rằng L là rỗng
- F = F1  F2 khi S là vô sinh.
-  được xây dựng: ((q, p), a, X) chứa ((q’, p’), ) nếu: Bài toán 2. Xác định xem xâu w có thuộc ngôn ngữ phi ngữ cảnh L
o 1(q, a, X) chứa (q’, ), và không?

o 2(p, a) = p’ Có nhiều cách khác nhau để giải quyết bài toán này, tuy nhiên thường có
độ phức tạp cao. Chẳng hạn, chúng ta xây dựng một ô-tô-mát đẩy xuống
Chúng ta dễ dàng chứng minh bằng quy nạp theo số bước dịch chuyển M đoán nhận L, sau đó thực hiện quá trình đoán nhận w trên M. Nếu sau
của ODX rằng (q01, w, Z) ├* (q, , ) khi và chỉ khi khi đọc xong w ô-tô-mát đạt đến một trong các trạng thái cuối thì w thuộc L,
((q01, q02), w, Z) ├* ((q, p), , ) với p = 2*(q02, w). Bởi vì, (q, p) là trạng thái ngược lại thì w không thuộc L.
cuối của M khi và chỉ khi q là trạng thái cuối của M1 và p là trạng thái cuối
của M2. Khi đó, M chấp nhận w khi và chỉ khi cả M1 và M2 chấp nhận w, Ngoài ra, đối với ngôn ngữ phi ngữ cảnh có một số vấn đề không thể
nghĩa là w thuộc L1  L2. được giải quyết bởi các thuật toán hiệu quả trên máy tính. Chúng ta gọi đó là
các vấn đề không thể xác định được (undecidable problems). Một số các vấn
Định lý 6.11. Nếu L1 là ngôn ngữ phi ngữ cảnh và L2 là ngôn ngữ chính quy đề sau là không thể xác định được:
thì L1 - L2 là ngôn ngữ phi ngữ cảnh.
- Một văn phạm phi ngữ cảnh là nhập nhằng?
Chứng minh: Chúng ta có L1 - L2 = L1  L 2 . Mà L2 là ngôn ngữ
- Một ngôn ngữ phi ngữ cảnh là nhập nhằng cố hữu?
chính quy thì L 2 cũng là ngôn ngữ chính quy (theo tính chất của ngôn
ngữ chính quy). Vậy theo định lý 6.10, L1 - L2 là ngôn ngữ phi ngữ cảnh. - Giao của hai ngôn ngữ phi ngữ cảnh có là rỗng?
Ngoài các tính chất của ngôn ngữ phi ngữ cảnh ở trên, chúng ta có nhận - Hai ngôn ngữ phi ngữ cảnh có giống hệt nhau?
xét sau: - Một ngôn ngữ phi cảnh có bằng *, trong đó  là bảng chữ của
- L1 và L2 là các ngôn ngữ phi ngữ cảnh, nhưng L1  L2 chưa ngôn ngữ này?
chắc là ngôn ngữ phi ngữ cảnh.
6.8 Nhận biết các ngôn ngữ không phi ngữ cảnh
- L ngôn ngữ phi ngữ cảnh, nhưng L chưa chắc là ngôn ngữ phi Chúng ta đã biết một ngôn ngữ phi ngữ cảnh được mô tả bởi một trong hai
ngữ cảnh. phương tiện:
6.7 Các thuật toán liên quan đến ngôn ngữ phi ngữ - ô-tô-mát đẩy xuống,
cảnh - văn phạm phi ngữ cảnh.
Tương tự như đối với ngôn ngữ chính quy, đối với ngôn ngữ phi cảnh Vấn đề đặt ra là làm thế nào để nhận biết một ngôn ngữ không là phi ngữ
chúng ta cũng cần giải quyết một số bài toán cơ bản như: một ngôn ngữ phi cảnh. Thế thì cũng tương tự như đối với ngôn ngữ chính quy, để nhận biết các
ngữ cảnh có rỗng không hay một xâu ký hiệu có thuộc một ngôn ngữ phi ngữ ngôn ngữ không phi ngữ cảnh chúng ta sử dụng định lý bơm cho ngôn ngữ
cảnh không. phi ngữ cảnh.
Bài toán 1. Xác định xem ngôn ngữ phi ngữ cảnh L có là rỗng không? Trước khi đề cập đến định lý bơm, chúng ta xem xét kích thước của một
cây dẫn xuất.

145 146
6.8.1 Kích thước cây dẫn xuất 2. vy  ,
Một trong những ưu điểm của dạng chuẩn Chomsky là chuyển cây dẫn 3. i  0, uvixyiz  L.
xuất thành một cây nhị phân, là loại cây có các tính chất được cài đặt dễ Chứng minh: Ý tưởng của việc chứng minh định lý là chỉ ra rằng cây
dàng bằng thuật toán trên máy tính.
dẫn xuất ứng với xâu đủ dài phải chứa một con đường mà trên đó cùng
Định lý 6.12. Giả sử cây dẫn xuất của một xâu w được sinh ra bởi một văn một ký hiệu không kết thúc (tức là biến) xuất hiện ít nhất hai lần. Như thế,
phạm phi ngữ cảnh có dạng chuẩn Chomsky. Nếu chiều dài của con đường hai phần cây dẫn xuất có gốc cùng là một ký hiệu không kết thúc có thể
dài nhất (từ gốc đến lá) của cây dẫn xuất bằng n, thì |w|  2n-1. lặp tùy ý lần.
Chứng minh: Chúng ta chứng minh bằng quy nạp theo n. Xét ngôn ngữ phi ngữ cảnh L - {} và khác rỗng (vì có chứa xâu w, |w|
> 0). Như thế, tồn tại văn phạm G ở dạng chuẩn Chomsky sao cho L(G) =
Bước cơ bản: Với n = 1. Chúng ta dễ dàng nhận thấy định lý đúng với
cây dẫn xuất có chiều dài con đường dài nhất là 1 sẽ bao gồm một nút gốc L - {}.
S và một nút lá có nhãn là ký hiệu kết thúc a (Hình 6.9). Xâu w chính là ký Giả sử G có m biến. Chọn n = 2m. Lấy w  L với |w|  n. Xét cây dẫn xuất
hiệu kết thúc a, như thế |w| = 1. Mà 2n-1 = 20 = 1. Vậy định lý đúng với T của xâu w. Theo định lý 6.12, nếu cây dẫn xuất mà con đường dài nhất của
n = 1. nó có chiều dài là m, thì xâu kết quả của cây có chiều dài nhỏ hơn hoặc bằng
Bước quy nạp: Giả sử chiều dài của con đường dài nhất trong cây dẫn 2m-1. Trong khi với xâu w mà chúng ta chọn, thì |w|  2m. Vậy cây T phải có
xuất là n với n > 1. Chúng ta dễ dàng nhận thấy rằng, nút gốc của cây dẫn một con đường có chiều dài tối thiểu là m + 1. Xét con đường dài nhất
xuất phải sử dụng luật sinh có dạng S → AB, chứ không thể sử dụng luật trong cây T, như minh họa trong hình 6.10. Con đường đó có chiều dài là k +
sinh dạng S → a, bởi vì n > 1 (Hình 6.9). Các cây con T1 và T2 có chiều 1, với k  m.
dài của con đường dài nhất phải nhỏ hơn n − 1, bởi vì các con đường này A0
không chứa cung từ S đến B hoặc C. Theo giả thuyết quy nạp, kết quả của
hai cây con T1 và T2 phải nhỏ hơn hoặc bằng 2n-2. Mà kết quả của cây dẫn A1
xuất có gốc là S là ghép nối kết quả của hai cây con T1 và T2, nghĩa là có
A2
chiều dài nhất là 2n-2 + 2n-2 = 2n-1. Vậy định lý được chứng minh.
S
S
A B Ak

a T1 T2
Hình 6.10. Con đường dài nhất trong cây T
Trên con đường này, có sự xuất hiện của k + 1 biến A0, A1, …, Ak. Mà k 
Hình 6.9. Minh họa cây dẫn xuất m, nên có ít nhất m + 1 sự xuất hiện biến trên con đường. Trong khi, N chỉ có
m biến, nên phải có ít nhất hai sự xuất hiện của các biến cuối cùng trên con
6.8.2 Định lý bơm cho ngôn ngữ phi ngữ cảnh đường cùng chính là một biến (nghĩa là các biến từ Ak-m đến Ak). Giả sử đó là
Định lý 6.13. Cho ngôn ngữ phi ngữ cảnh L. Tồn tại số nguyên các biến Ai và Aj (Ai = Aj), với k - m  i < j  k.
dương n, sao cho mọi xâu w  L với |w|  n có thể viết dưới dạng w
= uvxyz thỏa mãn các điều kiện sau:
1. |vxy|  n,
147 148
Như thế, chúng ta có thể chia cây T như minh họa trong hình 6.11. Vậy chúng ta suy ra:
S * * * *
S ⇒ uAz ⇒ uvAyz uv iAy zi ⇒ uv iy zi

Nghĩa là, i  0, uvixyiz  L. Cuối cùng, điều kiện 3 được thỏa mãn. Vậy
định lý đã được chứng minh.
Ai
6.8.3 Ứng dụng định lý bơm cho ngôn ngữ phi ngữ cảnh

Aj Ví dụ 6.11. Chứng minh ngôn ngữ L = {akbkck | k > 0} là không phi ngữ
cảnh.
Chúng ta chứng minh bằng phản chứng. Giả sử L là ngôn ngữ phi ngữ
cảnh. Vậy theo định lý bơm, tồn tại số nguyên dương n, mà chúng ta có thể
u v x y z chọn xâu w = anbncn, thỏa mãn |w|  n và chia xâu w thành uvxyz sao cho:
|vxy|  n và vy   và i  0, uvixyiz  L.
Hình 6.11. Chia cây dẫn xuất T
Tuy nhiên, chúng ta dễ dàng chỉ ra rằng không tồn tại cách chia xâu w như
Trong đó, x là kết quả của cây dẫn xuất có gốc là Aj, vxy là kết quả của cây trên.
dẫn xuất có gốc là Ai. Như thế, theo cây dẫn xuất trên, xâu w = uvxyz với u, v,
x, y, z có các tính chất: Bởi vì |vxy|  n, vậy vxy không thể đồng thời chứa ký hiệu a và ký hiệu c.
Vì trong xâu w ký hiệu a cuối cùng và ký hiệu c đầu tiên cách nhau n + 1
*
S ⇒ uA i z (a) vị trí. Như thế, có hai khả năng xảy ra:
* 1. Xâu vxy không chứa ký hiệu c. Nghĩa là vxy chỉ chứa ký hiệu a và
A ⇒ vA y (b)
i j
b, ít nhất là một trong hai ký hiệu này. Vậy xâu uxz chứa n ký
* hiệu c, nhưng ít hơn n ký hiệu a hoặc ít hơn n ký hiệu b. Như thế,
Aj ⇒ x (c) uxz (trường hợp i = 0) không thuộc L.

Theo cách chọn Ai với k - m  i, hay k - i  m. Như thế, chiều dài của con 2. Xâu vxy không chứa ký hiệu a. Tương tự, xâu uxz chứa n ký hiệu
đường dài nhất trong cây có gốc Ai nhỏ hơn hoặc bằng m + 1. Theo định lý a, nhưng ít hơn n ký hiệu b hoặc ít hơn n ký hiệu c. Như thế, uxz
6.12, thì |vxy|  2m = n. Như thế, điều kiện 1 được thỏa mãn. (trường hợp i = 0) không thuộc L.

Hơn nữa, vì văn phạm thỏa mãn dạng chuẩn Chomsky, nên không có Vậy giả thiết ban đầu của chúng ta không đúng, nghĩa là L không là
luật sinh đơn vị. Vậy từ (b) ta suy ra được vy  . Như thế, điều kiện 2 ngôn ngữ phi ngữ cảnh.
được thỏa mãn. Ví dụ 6.12. Chứng minh ngôn ngữ L = {aibjcidj | i > 0 và j > 0} là
Vì Ai = Aj = A nên chúng ta có thể thay Ai và Aj bởi A như sau: không phi ngữ cảnh.
* Giả sử L là ngôn ngữ phi ngữ cảnh. Vậy theo định lý bơm, tồn tại số
S ⇒ uAz nguyên dương n, mà ta có thể chọn xâu w = anbncndn, thỏa mãn |w|  n và
*
A ⇒ vAy chia xâu w thành uvxyz sao cho: |vxy|  n và vy   và i  0, uvixyiz  L.
Chúng ta sẽ chỉ ra rằng không tồn tại cách chia xâu w như trên.
*
A⇒x

149 150
Vì |vxy|  n nên vxy hoặc là xâu con của một ký hiệu (a, b, c, d) hoặc là a. S → aSb | A
xâu con của hai ký hiệu liên tiếp nhau (a và b, b và c, c và d). A → bAa | S | c
- Nếu vxy là xâu con của một ký hiệu, thì uxz chứa n lần của 3 ký b. S → abAS | aA
hiệu khác nhau và ít hơn n lần của ký hiệu thứ tư. Vậy uxz
không thuộc L. A → aAb | ab

- Nếu vxy là xâu con của hai ký hiệu liên tiếp nhau, giả sử đó là b Bài 6.4. Xây dựng văn phạm phi ngữ cảnh mô tả ngôn ngữ sau và sau đó
và c. Khi đó, uxz chứa ít hơn n ký hiệu b và ít hơn n ký hiệu c, chuyển văn phạm thành ODX đoán nhận ngôn ngữ đó.
trong khi chứa n ký hiệu a và n ký hiệu d. Vậy uxz không L = {aibjci+j | i > 0, j >0}
thuộc L.
Bài 6.5. Chuyển ODX M = ({p, q}, {a, b}, {X, Z}, , q, Z) thành văn
Vậy giả thiết ban đầu của chúng ta không đúng, nghĩa là L không là phạm phi ngữ cảnh tương đương,  được định nghĩa như sau:
ngôn ngữ phi ngữ cảnh.
(q, b, Z) = {(q, XZ)},
6.9 Bài tập chương 6 (q, b, X) = {(q, XX)},
Bài 6.1. Xây dựng ODX đoán nhận các ngôn ngữ sau: (q, a, X) = {(p, X)},
a. {aibjcj | i, j > 0} (q, , X) = {(q, )},
i j k
b. {a b c | i, j, k ≥ 0, i + j = k} (p, b, X) = {(p, )},
c. {aibjck | i, j, k ≥ 0, i + k = j} (p, a, Z) = {(q, Z)}.
i j k
d. {a b c | i, j, k ≥ 0, i + 2k = j} Bài 6.6. Xây dựng ô-tô-mát đẩy xuống đơn định đoán nhận các ngôn
e. {a b c | i  j hoặc j = k}
i j k ngữ sau:

f. {aibj | i, j ≥ 0, 2i = 3j} a. {anbn | n  0}

g. {aibj | i > j ≥ 0} b. {anbm | n  m}

Bài 6.2. Xây dựng ODX đoán nhận các ngôn ngữ sau: c. {anbman | n, m  0}

a. Gồm các xâu trên {0, 1} sao cho không có tiền tố nào có số Bài 6.7. Chứng minh các ngôn ngữ sau không là phi ngữ cảnh:
lượng ký hiệu 0 lớn hơn số lượng ký hiệu 1. a. {anbncm | n  m}
b. Gồm các xâu trên {0, 1} với số lượng bằng nhau của ký hiệu 0 b. {anbm | m  n2}
và ký hiệu 1.
c. {aibjck | i < j < k}
c. Gồm các xâu trên {0, 1} với số ký hiệu 0 gấp đôi số ký hiệu 1.
d. {ap | p là số nguyên tố}
d. Gồm các xâu trên {0, 1} với hai lần số ký hiệu 0 bằng ba lần số
e. {ww | w  {a, b}*}
ký hiệu 1.
Bài 6.3. Chuyển các văn phạm phi ngữ cảnh sau thành các ODX đoán
nhận cùng ngôn ngữ.

151 152
… B B X1 X2 Xi Xn B B …
Băng Đầu đọc
Chương 7. Máy Turing
q Bộ điều khiển
Trong các chương trước, chúng ta đã tìm hiểu hai loại mô hình tính
toán và đoán nhận: ô-tô-mát hữu hạn và ô-tô-mát đẩy xuống. Ô-tô-mát Hình vẽ 7.1. Mô hình máy Turing
hữu hạn chỉ có thể đoán nhận lớp ngôn ngữ đơn giản nhất là ngôn ngữ Máy Turing gồm:
chính quy, trong khi ô-tô-mát đẩy xuống cho phép đoán nhận lớp ngôn
ngữ phức tạp hơn là ngôn ngữ phi ngữ cảnh. Tuy nhiên, có các ngôn ngữ - Một bộ điều khiển với một số hữu hạn các trạng thái, trong đó
không phi ngữ cảnh, chẳng hạn {anbncn | n > 0} như chúng ta đã chứng có một trạng thái đầu và một số các trạng thái cuối hay trạng
minh, thì ô-tô-mát đẩy xuống không thể đoán nhận được. Vậy chúng ta thái thừa nhận.
cần một cơ chế mạnh hơn cho phép đoán nhận lớp các ngôn ngữ không - Một băng được chia thành ô, mỗi ô chứa một ký hiệu. Ban đầu,
phi ngữ cảnh. xâu vào gồm các ký hiệu từ bảng chữ vào được đặt trên băng.
Trong chương này, chúng ta sẽ trình bày mô hình mới, được gọi là máy Các ô còn lại trên băng vô hạn về phía bên trái và vô hạn về
Turing. Máy Turing, được A. M. Turing đề xuất năm 1936, như là một mô phía bên phải được lấp đầy bởi một ký hiệu đặc biệt, gọi là ký
hình trừu tượng cho mọi tính toán có thể. Tuy nhiên, máy Turing không chỉ hiệu trắng (blank), được ký hiệu là B hoặc #. Các ký hiệu trắng
là mô hình tính toán mà còn cho phép chúng ta đoán nhận các ngôn ngữ ở trên băng nhưng không thuộc bảng chữ vào.
phức tạp. Ngoài ra, nhờ máy Turing, chúng ta có thể nhận biết được các vấn - Một đầu đọc dịch chuyển trên băng. Đầu đọc ban đầu chỉ vào ô
đề “giải quyết được” hay “không giải quyết được” bởi máy tính. Tuy nhiên, chứa ký hiệu vào bên trái nhất trên băng.
trong khuôn khổ giáo trình này chúng ta chủ yếu chỉ tìm hiểu khả năng đoán
Một bước dịch chuyển của máy Turing phụ thuộc vào trạng thái hiện tại
nhận ngôn ngữ của máy Turing.
của bộ điều khiển và ký hiệu được đọc trên băng mà nó thực hiện:
7.1 Máy Turing 1. Thay đổi trạng thái. Tuy nhiên, trạng thái tiếp theo có thể là trạng
Có nhiều định nghĩa về các mô hình khác nhau của máy Turing, tuy thái hiện tại.
nhiên tất cả các mô hình này đều tương đương với nhau. Trước hết, chúng 2. Viết một ký hiệu lên ô đang được đọc thay thế cho ký hiệu cũ. Ký
ta sẽ xem xét mô hình máy Turing đơn giản nhất, được gọi là mô hình cơ hiệu mới được viết lên có thể là giống với ký hiệu hiện tại trên
bản. băng.

7.1.1 Mô tả máy Turing 3. Dịch chuyển đầu đọc sang phải hoặc sang trái một ô.
Máy Turing đoán nhận xâu vào khi nó đạt đến một trong các trạng thái
Chúng ta minh họa máy Turing trong hình 7.1.
cuối.
Như vậy, chúng ta nhận thấy máy Turing khác với ô-tô-mát hữu hạn là
đầu đọc có thể dịch chuyển tự do trên băng (sang phải hay sang trái) và
không những đọc mà còn có thể ghi.

153 154
Định nghĩa 7.1. Máy Turing được định nghĩa bởi bộ bảy: M = (Q, , , , q0, B, F)
M = (Q, , , , q0, B, F) trong đó:
trong đó: - Q = {q0, q1, q2, q3, q4},
- Q là tập hữu hạn các trạng thái, -  = {a, b},
-  là bảng chữ vào, -  = {X, Y, a, b, B},
-  là tập các ký hiệu sử dụng trên băng,  là tập con của , - F = {q4},
- q0  Q là trạng thái đầu, -  được xây dựng như sau:
- B   −  là ký hiệu trắng, 1. (q0, a) = (q1, X, R). Đọc ký hiệu a trái nhất.
- F  Q là tập hữu hạn các trạng thái cuối/thừa nhận, 2. (q1, a) = (q1, a, R). Vượt phải qua các ký hiệu a để tìm ký
-  là hàm dịch chuyển được định nghĩa như sau: hiệu b.

 : Q   → Q    {L, R}, 3. (q1, Y) = (q1, Y, R). Vượt phải qua các ký hiệu Y để tìm ký
hiệu b.
trong đó, L và R biểu diễn “trái” hay “phải” là hướng dịch chuyển
4. (q1, b) = (q2, Y, L). Gặp ký hiệu b tương ứng với ký hiệu a
của đầu đọc.
vừa thay thế trước đó.
Hay chúng ta có thể biểu diễn hàm dịch chuyển cụ thể như sau:
5. (q2, Y) = (q2, Y, L). Vượt trái qua các ký hiệu Y để tìm ký
(q, X) = (p, Y, D) với p, q  Q; X, Y  ; D  {L, R}. hiệu a trái nhất.
Nghĩa là, máy Turing đang ở trạng thái q và đọc ký hiệu X, thì máy 6. (q2, a) = (q2, a, L). Vượt trái qua các ký hiệu a để tìm ký
Turing sẽ ghi lên ô vừa đọc ký hiệu Y thay thế cho X, chuyển sang trạng thái hiệu a trái nhất.
p và dịch đầu đọc sang hướng D.
7. (q2, X) = (q0, X, R). Gặp ký hiệu X đầu tiên bên cạnh nó sẽ
Ví dụ 7.1. Xây dựng máy Turing đoán nhận ngôn ngữ {anbn | n > 0}. là ký hiệu a trái nhất cần tìm nếu có. Chuyển qua trạng
Chúng ta sẽ xây dựng máy Turing với ý tưởng là thay mỗi ký hiệu a bởi thái q0 để lặp lại chu trình xác định ký hiệu a và ký hiệu b
X và thay mỗi ký hiệu b bởi Y, cho đến khi tất cả các a được so khớp với các tương ứng.
b. 8. (q0, Y) = (q3, Y, R). Không còn tìm thấy ký hiệu a trái nhất.
Cụ thể, ban đầu, xuất phát từ ký hiệu vào trái nhất, thay ký hiệu a bởi X và 9. (q3, Y) = (q3, Y, R). Vượt phải qua các Y, tìm xem còn ký
dịch phải vượt qua các ký hiệu a và Y nếu gặp, cho đến khi gặp ký hiệu b. hiệu b nào nữa không.
Thay ký hiệu b đó bởi Y và dịch trái vượt qua các ký hiệu Y và a nếu gặp,
cho đến khi gặp ký hiệu X. Tại thời điểm này, thì dịch phải một ô, nếu tìm thấy 10. (q3, B) = (q4, B, R). Không còn tìm thấy thêm ký hiệu b nào
ký hiệu a thì thay nó bởi X và lặp lại chu trình trên để thay ký hiệu b ứng với nữa. Vậy đoán nhận xâu vào.
ký hiệu a đó bởi Y. Máy Turing sẽ đoán nhận xâu vào khi thay b bởi Y mà Hàm dịch chuyển của máy Turing cũng có thể được biểu diễn dạng
không tìm thấy thêm ký hiệu a nào nữa và cũng không tìm thấy thêm ký hiệu b bảng như sau:
nào nữa.  a b X Y B
Vậy máy Turing gồm các thành phần như sau: q0 (q1, X, R) (q3, Y, R)

155 156
q1 (q1, a, R) (q2, Y, L) (q1, Y, R) đọc tự do dịch chuyển trên băng, tức là dịch trái hoặc dịch phải. Nên tại
q2 (q2, a, L) (q0, X, R) (q2, Y, L) mỗi thời điểm, để mô tả cấu hình của máy Turing chúng ta phải mô tả toàn
q3 (q3, Y, R) (q4, B, R) bộ các ký hiệu trên băng, vị trí đầu đọc và trạng thái hiện tại của máy
q4 Turing.
Định nghĩa 7.2. Cho máy Turing M = (Q, , , , q0, B, F), cấu hình
7.1.2 Biểu diễn máy Turing bằng biểu đồ
máy Turing được định nghĩa bởi X1X2…Xi-1qXiXi+1…Xn, trong đó:
Tương tự như ô-tô-mát hữu hạn hay ô-tô-mát đẩy xuống, chúng ta cũng có
- q  Q là trạng thái của máy Turing,
thể sử dụng biểu đồ dịch chuyển biểu diễn máy Turing mà trong đó:
- đầu đọc chỉ vào ký hiệu Xi,
1. Các nút biểu diễn các trạng thái.
- X1X2…Xn là xâu trên băng từ bên trái nhất qua bên phải nhất
2. Có một mũi tên đi vào nút q0 để ký hiệu trạng thái đầu.
chứa các ký hiệu khác ký tự trắng B.
3. Các trạng thái kết thúc F là các nút được biểu diễn bởi hai vòng
Định nghĩa 7.3. Cho máy Turing M = (Q, , , , q0, B, F), chúng ta
tròn.
định nghĩa dịch chuyển cấu hình, ký hiệu bởi├, như sau:
4. Các trạng thái không thuộc F là các nút được biểu diễn bởi chỉ
một vòng tròn. - Nếu (q, Xi) = (p, Y, L) thì chúng ta có dịch chuyển cấu hình
sau:
5. Các cung tương ứng với các dịch chuyển. Một cung từ trạng
thái q đến trạng thái p được gán nhãn X / Y, D nghĩa là X1X2…Xi-1qXiXi+1…Xn├ X1X2… Xi-2pXi-1YXi+1…Xn
(q, X) = (p, Y, D). Có hai trường hợp đặc biệt, khi i = 1, thì dịch chuyển có dạng:
Ví dụ 7.2. Biểu diễn máy Turing trong ví dụ 7.1 bằng biểu đồ dịch qX1X2…Xn├ pBYX2…Xn
chuyển. X / X, R Khi i = n và Y = B thì dịch chuyển có dạng:
a / a, R X1X2…Xn-1qXn├ X1X2… Xn-2pXn-1
- Nếu (q, Xi) = (p, Y, R) thì ta có dịch chuyển cấu hình sau:
a / X, R b / Y, L
q0 q1 q2 X1X2…Xi-1qXiXi+1…Xn├ X1X2… Xi-1YpXi+1…Xn
Y / Y, L Có hai trường hợp đặc biệt, khi i = n, thì dịch chuyển có dạng:
Y / Y, R Y / Y, R
a / a, L X1X2…Xn-1qXn├ X1X2… Xn-1YpB
Y / Y, R
q3 B / B, R q4 Khi i = 1 và Y = B thì dịch chuyển có dạng:
qX1X2…Xn├ pX2…Xn
Tương tự như ODX, chúng ta sử dụng ký hiệu ├* để biểu diễn dịch
Hình 7.2. Máy Turing đoán nhận ngôn ngữ {anbn | n > 0} chuyển từ không đến nhiều cấu hình.
7.1.3 Cấu hình của máy Turing Ví dụ 7.3. Thực hiện đoán nhận xâu aabb bởi máy Turing được xây
dựng ở ví dụ 7.1.
Cũng tương tự như ô-tô-mát đẩy xuống, máy Turing có khái niệm cấu
hình. Tuy nhiên, đối với máy Turing, băng vô hạn về cả hai phía và đầu

157 158
q0aaabbb├ Xq1aabbb├ Xaq1abbb├ Xaaq1bbb├ Xaq2aYbb├ với  được xây dựng như sau:
Xq2aaYbb├ q2XaaYbb├ Xq0aaYbb├ XXq1aYbb├ XXa q1Ybb├ 1. (q0, 0) = (q0, 0, R). Dịch phải tìm ký hiệu cuối cùng.
XXaYq1bb├ XXaq2YYb├ XXq2aYYb├ Xq2XaYYb├ XXq0aYYb├
XXXq1YYb├ XXXYq1Yb├ XXXYYq1b├ XXXYYq2Y├ 2. (q0, 1) = (q0, 1, R). Dịch phải tìm ký hiệu cuối cùng.
XXXYq2YY├ XXXq2YYY├ XXq2XYYY├ XXXq0YYY├ 3. (q0, B) = (q1, B, L). Gặp ký hiệu cuối.
XXXYq3YY├ XXXYYq3Y├ XXXYYYq3B├ XXXYYYBq4B.
4. (q1, 0) = (q2, 1, R). Nếu ký hiệu cuối là 0 thì thay bởi 1 và
Hay chúng ta có thể mô tả ngắn gọn hơn: q0aaabbb├* XXXYYYBq4B. kết thúc.
5. (q1, 1) = (q1, 0, L). Nếu ký hiệu cuối là 1 thì thay bởi 0 và
7.1.4 Ngôn ngữ được đoán nhận bởi máy Turing dịch trái.
Chúng ta vừa nhận thấy máy Turing đoán nhận ngôn ngữ. Nó bắt đầu đọc
6. (q1, B) = (q2, 1, R). Nếu gặp ký hiệu B bên trái thì thay
ký hiệu trái nhất của xâu vào trên băng và nếu nó đạt đến một trong các
bởi 1 và kết thúc.
trạng thái cuối thì xâu vào được thừa nhận.
Ví dụ 7.5. Xây dựng máy Turing tính hàm f(m, n) = m + n, với m và n là
Định nghĩa 7.4. Cho máy Turing M = (Q, , , , q0, B, F). Ngôn ngữ
các số nguyên dương.
được đoán nhận bởi máy Turing được định nghĩa:
Khi tính toán trên các số nguyên dương bởi máy Turing, cách biểu diễn
L(M) = {w  * | q0w├* p},
bằng các chữ số nhị phân không thuận tiện bằng việc biểu diễn mỗi số
trong đó p  F; ,   *. nguyên n bởi n + 1 ký hiệu 1 (chúng ta sử dụng n + 1 ký hiệu, vì muốn biểu
Định nghĩa 7.5. Ngôn ngữ được đoán nhận bởi máy Turing được gọi là diễn được số 0).
ngôn ngữ liệt kê đệ quy. Khi đặt trên băng, hai số nguyên m và n được cách nhau bởi ký hiệu
trắng B. Như thế, phép cộng thực ra là thay ký hiệu trắng bởi ký hiệu 1 và
7.2 Tính toán bởi máy Turing xóa bớt hai ký hiệu 1 trên băng.
Như chúng ta đã biết máy Turing không chỉ đoán nhận ngôn ngữ mà còn M = ({q0, q1, q2, q3}, {1}, {1, B}, , q0, B, {q2})
có thể thực hiện các tính toán.
với  được xây dựng như sau:
Định nghĩa 7.6. Máy Turing tính hàm f: * → * nếu với một xâu vào w
bất kỳ, máy Turing luôn dừng trong một cấu hình mà f(w) ở trên băng. Hàm 1. (q0, 1) = (q1, B, R). Thay ký hiệu 1 thứ nhất bởi B.
f được gọi là hàm tính được (computable function). 2. (q1, 1) = (q2, B, R). Thay ký hiệu 1 thứ hai bởi B.
Ví dụ 7.4. Xây dựng máy Turing tính hàm f(n) = n + 1, với n là số 3. (q2, 1) = (q2, 1, R). Dịch phải để tìm ký hiệu B ngăn hai số m và n.
nguyên dương.
4. (q2, B) = (q3, 1, R). Thay ký hiệu B bởi 1 và kết thúc.
Chúng ta sẽ biểu diễn n bởi dãy nhị phân. Khi đó, chúng ta sẽ thực hiện
5. (q1, B) = (q3, B, R). Trường hợp m = 0, thì n chính là kết quả.
phép cộng 1 vào dãy nhị phân. Máy Turing sẽ thực hiện: tìm ký hiệu cuối
cùng của dãy nhị phân, nếu đó là ký hiệu 0 thì thay bởi 1 và kết thúc, nếu đó 7.3 Luận đề Church-Turing
là ký hiệu 1 thì thay bởi 0 và dịch trái lặp lại quá trình trên. Nếu cuối cùng
gặp ký hiệu trắng B bên trái thì thay bởi 1 và kết thúc. Quá trình đoán nhận xâu vào hay tính toán hàm có thể xảy ra các tình
huống sau:
M = ({q0, q1, q2}, {0, 1}, {0, 1, B}, , q0, B, {q2})
1. Chuỗi các các cấu hình chứa một trạng thái cuối.

159 160
2. Chuỗi các cấu hình kết thúc bởi vì
- hoặc hàm dịch chuyển không được định nghĩa, q

- hoặc máy Turing dịch trái từ ô đầu tiên trên băng.


A B C
3. Chuỗi các các cấu hình không chứa trạng thái cuối và nó vô
hạn.
Hình 7.3. Ví dụ nhớ ở trạng thái
Trong hai trường hợp đầu tiên, chúng ta có thủ tục hiệu quả. Luận đề
Ví dụ 7.6. Xây dựng máy Turing đoán nhận ngôn ngữ L(01* + 10*).
Church-Turing liên quan đến khái niệm thủ tục hiệu quả.
Chúng ta sẽ xây dựng mỗi trạng thái gồm [q a]: trạng thái điều khiển q
Luận đề Church-Turing được phát biểu như sau: “Các hàm tính toán
và một ký hiệu a  {0, 1}. Máy Turing sẽ thực hiện: khi đọc ký hiệu đầu
được bởi các thủ tục hiệu quả thì cũng được tính bởi máy Turing”.
tiên của xâu vào sẽ ghi nhớ vào thành phần thứ hai của trạng thái và sau
Có thể hiểu rằng, các bài toán giải được trong thực tế thì sẽ được tính toán đó kiểm tra xem ký hiệu này có xuất hiện trong phần còn lại của xâu vào
bởi máy Turing. Như thế, chúng ta có thể thấy luận đề Church-Turing chủ không.
yếu liên quan đến vấn đề tính toán bởi máy Turing. Luận đề này được ứng
M = (Q, {0,1 }, {0, 1, B}, , [q0, B], [q1, B])
dụng để nghiên cứu về lý thuyết tính toán. Đây là vấn đề vượt quá khuôn
khổ của giáo trình này. trong đó: Q = {q0, q1}  {0, 1, B}.
Tuy nhiên, chúng ta có thể hiểu luận đề đối với ngôn ngữ, là vấn đề Hàm dịch chuyển  được định nghĩa như sau:
chúng ta quan tâm: “Các ngôn ngữ được đoán nhận bởi các thủ tục hiệu quả 1. ([q0, B], 0) = ([q1, 0], 0, R). Đọc ký hiệu đầu tiên là 0 và ghi nhớ
thì cũng được đoán nhận bởi máy Turing”. nó vào trạng thái.
Nghĩa là, các ngôn ngữ mà tồn tại các phương pháp đoán nhận chúng, thì 2. ([q0, B], 1) = ([q1, 1], 1, R). Đọc ký hiệu đầu tiên là 1 và ghi nhớ
tồn tại máy Turing đoán nhận chúng. nó vào trạng thái.
7.4 Các kỹ thuật xây dựng máy Turing 3. ([q1, 0], 1) = ([q1, 0], 1, R). Đọc các ký hiệu 1 sau khi đã đọc ký
hiệu 0.
Mô hình máy Turing mà chúng vừa xem xét là mô hình đơn giản nhất.
Ngoài ra, còn có một số các kỹ thuật khác để xây dựng bộ điều khiển và 4. ([q1, 1], 0) = ([q1, 1], 0, R). Đọc các ký hiệu 0 sau khi đã đọc ký
băng của máy Turing. Các kỹ thuật này cho phép Máy Turing thực hiện dễ hiệu 1.
dàng hơn các tính toán. 5. ([q1, 0], B) = ([q1, B], 0, R). Đoán nhận.
7.4.1 Nhớ ở bộ điều khiển hữu hạn 6. ([q1, 1], B) = ([q1, B], 0, R). Đoán nhận.
Chúng ta có thể thiết kế mỗi trạng thái của máy Turing không chỉ lưu giữ 7.4.2 Băng nhiều rãnh
trạng thái điều khiển mà còn lưu giữ một lượng dữ liệu. Chẳng hạn, một
trạng thái như hình 7.3 gồm trạng thái điều khiển q và ba phần tử dữ liệu A, B Băng của máy Turing có thể gồm nhiều rãnh. Mỗi ô trên rãnh chứa một
và C, nghĩa là một trạng thái được biểu diễn [q, A, B, C]: ký hiệu, như thế mỗi ký hiệu vào sẽ là một bộ các ký hiệu, mỗi ký hiệu
trên một rãnh. Chẳng hạn, ký hiệu vào [X, Y, Z] đối với băng có ba rãnh.
Cũng tương tự như kỹ thuật nhớ ở bộ điều khiển, sử dụng băng nhiều
rảnh, máy Turing không mở rộng khả năng của nó. Đó chỉ là một cách tổ
chức băng vào.

161 162
Ví dụ 7.7. Xây dựng máy Turing có băng hai rãnh đoán nhận ngôn ngữ 6. ([q4, B], [*, a]) = ([q4, B], [*, a], L). M dịch trái vượt qua
không phi ngữ cảnh L = {wcw | w  (0 + 1)+}. các ký hiệu đã được đánh dấu.
Một rãnh được dùng để chứa xâu vào cần đoán nhận, một rãnh dùng để 7. ([q4, B], [B, c]) = ([q5, B], [B, c], L). Khi M gặp ký hiệu c,
đánh dấu ký hiệu đã được xem xét. Máy Turing được xây dựng như sau: chuyển sang trạng thái q5 và chuyển sang trái. Ở trạng
M = (Q, , , , [q1, B], [B, B], {[q9, B]}) thái q5, tùy thuộc vào ký hiệu được đọc ngay bên trái c là
được đánh dấu hay chưa mà M tiếp tục thực hiện. Nếu ký
trong đó: hiệu đó đã được đánh dấu, nghĩa là phần w bên trái c đã
Q: Tập các trạng thái là {q1, q2, …, q9}  {0, 1, B}, nghĩa là chúng được đọc; cần kiểm tra thêm toàn bộ w bên phải c đã được
ta sử dụng kỹ thuật ghi nhớ ở bộ điều khiển hữu hạn, mỗi trạng đánh dấu và không còn ký hiệu nào chưa được đánh dấu,
thái là một cặp trạng thái điều khiển và thành phần dữ liệu. như thế thừa nhận xâu vào. Nếu ký hiệu ngay bên trái c
chưa được đánh dấu, tìm ký hiệu chưa được đánh dấu trái
: Tập các ký hiệu là {B, *}  {0, 1, c, B}. Rãnh thứ nhất gồm các nhất, và bắt đầu lại chu trình trên với trạng thái q1.
ký hiệu trắng và ký hiệu *. Chúng ta sử dụng ký hiệu * để đánh
dấu các ký hiệu của phần xâu w ở bên phải và bên trái của ký 8. ([q5, B], [B, a]) = ([q6, B], [B, a], L). Dịch chuyển này
hiệu c đã được so khớp. Rãnh thứ hai chứa các ký hiệu vào thực sự được thực hiện, khi ký hiệu ngay bên trái c chưa được đánh
của xâu. dấu. M chuyển sang trạng thái q6, dịch trái và tìm kiếm ký
hiệu đã được đánh dấu.
: Bảng chữ vào gồm các ký hiệu [B, 0] và [B, 1].
9. ([q6, B], [B, a]) = ([q6, B], [B, a], L). Chừng nào các ký
: Hàm dịch chuyển được định nghĩa ở dưới, trong đó a và b có thể hiệu chưa được đánh dấu, M tiếp tục ở trạng thái q6 và dịch
đại diện cho 0 hoặc 1. trái.
1. ([q1, B], [B, a]) = ([q2, a], [*, a], R). Ở trạng thái đầu, 10. ([q6, B], [*, a]) = ([q1, B], [*, a], R). Khi ký hiệu đã được
M đọc ký hiệu a (đại diện cho 0 hoặc 1), lưu trữ nó trong đánh dấu được tìm thấy, M chuyển sang trạng thái q1 và
bộ điều khiển, chuyển sang trạng thái q2, đánh dấu ký hiệu dịch phải để đọc ký hiệu chưa được đánh dấu.
vừa đọc và chuyển sang phải.
11. ([q5, B], [*, a]) = ([q7, B], [*, a], R). Dịch chuyển này
2. ([q2, a], [B, b]) = ([q2, a], [B, b], R). M chuyển sang phải được thực hiện, khi ký hiệu ngay bên trái c đã được đánh
tìm kiếm ký hiệu c. dấu và M ở trạng thái q5. M chuyển sang trạng thái q7 và
3. ([q2, a], [B, c]) = ([q3, a], [B, c], R). Khi M tìm thấy ký dịch phải.
hiệu c, tiếp tục sang phải, nhưng thay đổi sang trạng thái q3. 12. ([q7, B], [B, c]) = ([q8, B], [B, c], R). M ở trạng thái q7,
4. ([q3, a], [*, b]) = ([q3, a], [*, b], R). Ở trạng thái q3, M bỏ đảm bảo rằng đọc c và chuyển sang trạng thái q8.
qua các trạng thái đã đánh dấu. 13. ([q8, B], [*, a]) = ([q8, B], [*, a], R). M ở trạng thái q8 và
5. ([q3, a], [B, a]) = ([q4, B], [*, a], L). Nếu ký hiệu đầu tiên dịch phải vượt qua các ký hiệu đã được đánh dấu.
mà M tìm thấy giống với ký hiệu ghi nhớ trong bộ điều 14. ([q8, B], [B, B]) = ([q8, B], [B, B], R). Nếu M ở trạng thái
khiển, thì đánh dấu ký hiệu này, bởi vì ký hiệu này (trong w q8 đọc ký hiệu trắng và không gặp một ký hiệu 0 hay 1 nào
ở bên phải c) khớp với ký hiệu trong w ở bên trái c. M chưa được đánh dấu thì M thừa nhận xâu vào. Ngược lại,
chuyển sang trạng thái q4, xóa ký hiệu ghi nhớ ở bộ điều nếu M gặp một ký hiệu 0 hay 1 chưa được đánh dấu, thì
khiển và chuyển sang trái.

163 164
phần w bên phải và bên trái c không khớp nhau, M dừng và hiệu 1. Lúc này, nó sử dụng trạng thái q4 để thay các ký hiệu X trở lại ký
không thừa nhận xâu vào. hiệu 0, và kết thúc ở trạng thái q5.

7.4.3 Chương trình con Máy Turing thực hiện phép nhân bắt đầu ở trạng thái q0. Đầu tiên, nó
chuyển từ cấu hình q00m10n1 thành cấu hình 0m-11 q10n1 qua nhiều bước
Cũng giống như đối với các chương trình bình thường, máy Turing có thể khác nhau. Các dịch chuyển này được trình bày một phần trong hình 7.5
được xây dựng gồm nhiều chương trình con tương tác với nhau. Mỗi chương cho đến bên trái của lời gọi chương trình con. Các dịch chuyển này chỉ liên
trình con được gọi lúc cần và thực hiện xong chương trình con thì trở về tiếp quan đến các trạng thái q0 và q6.
tục thực hiện chương trình chính.
X / X, R
Mỗi chương trình con được tính bởi máy Turing gồm một tập hợp riêng
các trạng thái, trong đó có trạng thái đầu và trạng thái cuối. Khi gọi
chương trình con thì máy Turing chuyển về trạng thái đầu của chương
trình con. Sau khi kết thúc chương trình con, máy Turing chuyển từ trạng 0 / X, R B / 0, L
q1 q2 q3
thái cuối của chương trình con về trạng tiếp theo để thực hiện chương
trình chính. 0 / 0, R
1 / 1, L 1 / 1, R
Ví dụ 7.8. Xây dựng máy Turing thực hiện phép nhân hai số nguyên 0 / 0, L
dương m và n. Máy Turing được thiết kế bắt đầu với xâu 0m10n1 trên băng X / 0, L 1 / 1, R
và kết thúc với xâu 0mn trên băng. Ý tưởng xây dựng máy Turing như sau: q4
1 / 1, L
q5

1. Trong trường hợp tổng quát, băng sẽ có một xâu có dạng 0i10n10kn.
Hình 7.4. Chương trình con Copy
2. Ở mỗi bước cơ bản, chúng ta thay một ký hiệu 0 ở nhóm đầu bởi ký
hiệu B và thêm n ký hiệu 0 vào nhóm cuối, như thế cho chúng ta Phần bên phải của lời gọi chương trình con trong hình 7.5 liên quan đến
các trạng thái từ q7 đến q12. Sau khi thực hiện chương trình con Copy, các
xâu có dạng 0i-110n10(k+1)n.
trạng thái q7, q8 và q9 nhằm quay trở lại trạng thái q0. Chúng ta lại tiếp tục
3. Kết quả cuối cùng, chúng ta chép nhóm n ký hiệu 0 vào nhóm cuối thực hiện chương trình con Copy để chép n ký hiệu 0 tiếp theo.
m lần và mỗi lần như thế thay thế ký hiệu 0 trong nhóm đầu bởi B.
Trường hợp đặc biệt, khi ở trạng thái q8, nếu tất cả m ký hiệu 0 đã được
Khi nhóm đầu hoàn toàn được thay thế bởi các ký hiệu trắng, thì sẽ
thay bởi ký hiệu trắng (nghĩa là k = m), thì chuyển đến trạng thái q10. Các
có mn ký hiệu 0 ở nhóm cuối.
trạng thái q10 và q11 thay các ký hiệu 10n1 bởi các ký hiệu trắng, sau đó
4. Bước cuối cùng, chúng ta chuyển xâu 10n1 thành các ký hiệu trắng. chuyển sang trạng thái cuối q12. Khi đó, cấu hình của máy Turing
Bước xử lý quan trọng trong thuật toán này là một chương trình con, là q120mn.
chúng ta gọi là Copy. Chương tình con này cài đặt bước (2) ở trên, chép n
ký hiệu 0 vào nhóm cuối. Chính xác hơn, Copy chuyển cấu hình có dạng
0m-k1q10n10(k-1)n sang cấu hình có dạng 0m-k1q50n10kn. Máy Turing biểu
diễn chương trình con Copy được trình bày trong hình 7.4. Chương trình
con này đánh dấu ký hiệu 0 thứ nhất bởi X, chuyển sang phải trong trạng
thái q2 cho đến khi tìm thấy một ký hiệu trắng, chép các ký hiệu 0 ở đó, và
chuyển sang trái trong trạng thái q3 để tìm ký hiệu đánh dấu X. Chương
trình con lặp lại bước trên cho đến khi ở trạng thái q1, nó tìm thấy một ký

165 166
0 / 0, L
B / B, R - Tất cả các đầu đọc trên các băng khác có thể chỉ vào bất kỳ ô
q0 q9
nào trên băng tương ứng, vì khởi đầu tất cả các ô trên các băng
này đều là ký hiệu trắng.
0 / B, R 0 / 0, L
Bộ điều khiển
Copy
q6 1 / 1, R 0 / 0, L 1 / 1, L
q1 q5 q7 q8

0 / 0, R B / B, R

1 / B, R 1 / B, R
q12 q11 q10

0 / B, R
Hình 7.5. Máy Turing thực hiện phép nhân sử dụng Copy Hình 7.6. Máy Turing có nhiều băng
Mỗi bước dịch chuyển phụ thuộc vào trạng thái hiện tại và ký hiệu
7.5 Các mô hình khác của máy Turing đang đọc mà thực hiện:
Ngoài mô hình cơ bản của máy Turing, còn có một số mô hình mở rộng
- Chuyển trạng thái.
phức tạp hơn, tuy nhiên chúng đều tương đương với mô hình cơ bản của
máy Turing. - Trên mỗi băng, ký hiệu đang được đọc được thay thế bởi ký
hiệu mới.
7.5.1 Máy Turing có nhiều băng
- Mỗi đầu đọc thực hiện dịch chuyển sang trái, sang phải hay giữ
Máy Turing này gồm có một bộ điều khiển hữu hạn, một số hữu hạn các nguyên vị trí một cách độc lập.
băng và mỗi đầu đọc cho mỗi băng (Hình 7.6). Mỗi băng được chia thành ô,
mỗi ô chứa một ký hiệu. Các ký hiệu trên băng gồm các ký hiệu của bảng 7.5.2 Máy Turing không đơn định
chữ vào và ký hiệu trắng. Các trạng thái gồm có trạng thái đầu và các trạng Cũng tương tự như khái niệm ô-tô-mát hữu hạn đơn định và ô-tô-mát
thái cuối. hữu hạn không đơn định, máy Turing không đơn định khác với máy
Khởi đầu: Turing đơn định ở định nghĩa hàm dịch chuyển, ở mỗi bước nó có một số khả
năng lựa chọn trong quá trình dịch chuyển. Nghĩa là hàm dịch chuyển
- Xâu vào được đặt trên băng thứ nhất.
 của máy Turing không đơn định đối với mỗi trạng thái q và ký hiệu trên
- Tất cả các ô của các băng còn lại được lấp đầy bởi ký hiệu băng X, thì (q, X) cho kết quả là tập hợp các bộ ba:
trắng.
{(q1, Y1, D1), (q2, Y2, D2), …, (qk, Yk, Dk)}
- Bộ điều khiển ở trạng thái đầu.
với k là mộ số tự nhiên hữu hạn.
- Đầu đọc chỉ đến ký hiệu vào trái nhất trên băng thứ nhất.
Tuy nhiên, tính không đơn định không mở rộng khả năng của máy
Turing. Thật vậy, một ngôn ngữ được đoán nhận bởi máy Turing không đơn
định thì nó cũng được thừa nhận bởi máy Turing đơn định.

167 168
7.6 Bài tập chương 7
Bài 7.1. Xây dựng máy Turing đoán nhận các ngôn ngữ sau:
a. {anbncn | n > 0}
b. {wwR | w  {a, b}*} Tài liệu tham khảo
c. {ww | w  {a, b}*}
d. {wwRw | w  {a, b}*}
e. {ambncn+m | n,m ≥ 0}
[1] J. E. Hopscoft, R. Motwani, J. D. Ullman, Introduction to Automata
Bài 7.2. Xây dựng máy Turing tính các hàm sau: Theory, Languages and Computation, Addsion - Wesley, 2001.
a. f(n) = n - 1 với n > 0. [2] A. Stoughton, An Introduction to Formal Language Theory that
b. Cho n và m là các số nguyên dương, Integrates Experimentation and Proof, GNU, 2004.

f(n, m) = 0 nếu n  m, [3] J. M. Autebert, Théorie des langages et des automats, Masson, 1994.

f(n, m) = 1 nếu n < m [4] Ding-Zhu Du, Ker-I Ko, Problem solving in automata, languages, and
complexity, John Wiley & Sons, 2001.
Bài 7.3. Xây dựng máy Turing tính hàm:
[5] Nguyễn Văn Ba, Ngôn ngữ hình thức, NXB Khoa học và Kỹ thuật,
f(n, m) = n - m nếu n  m, 2002.
f(n, m) = 0 nếu n < m, [6] Hồ Văn Quân, Giáo trình lý thuyết Automat và ngôn ngữ hình thức,
với m và n là các số nguyên dương. NXB Đại học Quốc gia TP. Hồ Chí Minh, 2002.
[7] Thomas Niemann, A compact guide to LEX & YACC,
epaperpress.com.

169 170

You might also like