Các thuật toán nén LZ

Một phần của tài liệu Nghiên cứu phối hợp hai phương pháp nén và mã hóa thông tin (Trang 66 - 80)

1/. Thuật toán LZ77

LZ77 đƣợc phát minh ra năm 1977. Nó sử dụng từ điển là một đoạn văn bản gần với hiện tại.

Quá trình nén

Gọi vị trí kí tự đang đọc là hiện tại.

Gọi khoảng văn bản bắt đầu từ vị trí của kí tự đang đƣợc đọc đến hết văn bản là tƣơng lai.

Gọi khoảng văn bản từ bắt đầu văn bản đến ngay trƣớc vị trí kí tự đang đƣợc đọc là quá khứ.

Chúng ta chỉ tìm trong một khoảng N kí tự của quá khứ mà gần hiện tại nhất và tìm trong khoảng F kí tự đầu tiên trong tƣơng lai và gọi F kí tự này là buffer.

Nguyên tắc nén như sau:

Bước 1: F – 1 kí tự đầu tiên giữ nguyên.

Bước 2: Cho buffer gồm F kí tự trong tƣơng lai dịch dần về quá khứ N lần. Mỗi lần đếm số kí tự trùng nhau liên tiếp kể từ đầu của buffer với quá khứ và ghi nhớ con số ấy tƣơng ứng với các vị trí quá khứ mà buffer dịch đến. Tìm số lớn nhất trong tất cả các con số ấy.

Bước 3: Ghi ra mã gồm [i, j, w] trong đó i là khoảng cách từ vị trí hiện tại đến vị trí tƣơng ứng với số lớn nhất vừa tìm đƣợc, j là số các kí tự trùng nhau hay chính là số lớn nhất vừa tìm đƣợc, w là kí tự ở vị trí thứ j + 1 trong buffer.

Bước 4: Lặp lại bƣớc 2 cho đến khi hết văn bản.

Quá trình giải nén

Bước 1: Đọc F – 1 kí tự đầu tiên của bản mã ghi ra bản giải mã.

Bước 2: Đọc một bộ mã [i, j, w]. Lùi về đoạn văn bản đã giải mã i vị trí và copy j kí tự từ vị trí thứ i đó để ghi ra bản giải mã, sau đó ghi ra w.

Bước 3: Nếu còn bộ mã thì quay lại bƣớc 2. Nếu không còn thì kết thúc.

Ví dụ:

Quá trình nén nhƣ sau:

TT Quá khứ Vị trí hiện tại Buffer Ghi ra

1 bca

2 bca 4 bbcb [3,1,b]

3 bcabb 6 cbcc [4,1,b]

4 bcabbcb 8 ccba [2,1,c]

5 bcabbcbcc 10 baba [3,1,a]

6 bcabbcbccba 12 babc [2,2,b]

7 bcabbcbccbaba 15 c [5,1,””]

Bảng 3.4: Quá trình nén xâu “bcabbcbccbababc” theo thuật toán LZ77

Bản mã là bca[3,1,b][4,1,b][2,1,c][3,1a][2,2,b][5,1,””]

Quá trình giải nén

TT Bộ mã đọc vào Ghi ra Bản giải mã

1 bca bca 2 [3,1,b] bb bcabb 3 [4,1,b] cb bcabbcb 4 [2,1,c] cc bcabbcbcc 5 [3,1,a] ba bcabbcbccba 6 [2,2,b] bab bcabbcbccbabab 7 [5,1,””] c bcabbcbccbababc (adsbygoogle = window.adsbygoogle || []).push({});

Bảng 3.5: Quá trình giải nén theo thuật toán LZ77bản mã bca[3,1,b][4,1,b][2,1,c][3,1a][2,2,b][5,1,””]

2/. Thuật toán LZ78

Đây là một trong các thuật toán từ điển động khá mạnh đƣợc phát minh và sử dụng trong những năm 1978. Từ điển xây dựng trong mã hoá và giải mã đơn giản và hoàn toàn động, do đó không cần lƣu từ điển cùng file nén.

Quá trình nén

Thuật toán nén.

Bước 1: Khởi tạo từ điển có một phần tử là xâu rỗng có chỉ số 0. Xâu trung gian P rỗng.

Bước 2: Đọc kí tự tiếp theo trong văn bản vào C.

Bước 3: Tìm khúc (P + C) đã có trong từ điển chƣa? Nếu có thì P ← P + C và quay lại bƣớc 2. Nếu không thì:

i. Cập nhật P + C vào trong từ điển. ii. W ← chỉ số của P trong từ điển. iii. Ghi cặp (W, C) ra bản mã. iv. P ← rỗng.

Bước 4: Còn kí tự trong văn bản vào? Nếu còn thì quay lại bƣớc 2.

Sơ đồ nén

Hình 3.11: Sơ đồ nén LZ78

Bắt đầu

Khởi tạo từ điển. Xâu trung gian P rỗng

Đọc kí tự tiếp theo vào C

P + C đã có

trong từ điển? P ← P + C

W ← chỉ số của P trong từ điển

Ghi ra bản mã (W, C) Cập nhật P + C vào từ điển P ← rỗng Còn kí tự trong văn bản? C ← rỗng Kết thúc Ghi ra bản mã (W, C) Đúng Đúng Sai Sai

Quá trình giải nén

Với mỗi cặp (W, C) ta ký hiệu .W nội dung của đoạn copy thứ W trong từ điển. Nếu W = 0 thì .W là rỗng.

Thuật toán giải nén.

Bước 1: Khởi tạo từ điển có một phần tử là xâu rỗng có chỉ số 0. Bước 2: Đọc một cặp (W, C).

Bước 3: Ghi xâu (.W + C) ra bản giải mã. Cập nhật xâu này vào từ điển.

Bước 4: Còn kí tự trong bản mã không?

Nếu còn thì đọc cặp (W, C) tiếp theo và quay lại bƣớc 2. Nếu không thì kết thúc.

Sơ đồ giải nén

Hình 3.12: Sơ đồ giải nén thuật toán LZ78

Bắt đầu

Khởi tạo từ điển (adsbygoogle = window.adsbygoogle || []).push({});

Đọc một cặp (W, C) Ghi (.W + C) ra bản giải mã Cập nhật (.W + C) vào từ điển Còn kí tự trong bản mã? Kết thúc Đúng Sai

Ví d:

Cho văn bản aaabbabaabaaabab.

Quá trình nén TT Đoạn văn bản đã P C Từ điển W Ghi ra 1 a “” a 0 – “”, 1 – a 0 (0,a) 2 aaa a a 0 – “”, 1- a, 2 - aa 1 (1,a) 3 aaab “” b 0 – “”, 1- a, 2 – aa, 3- b 0 (0,b) 4 aaabba b a 0 – “”, 1- a, 2 – aa, 3 – b, 4 - ba 3 (3,a) 5 aaabbabaa ba a 0 – “”, 1- a, 2 – aa, 3 – b, 4 – ba,

5 – baa 4 (4,a)

6 aaabbabaabaaa baa a 0 – “”, 1- a, 2 – aa, 3 – b, 4 – ba,

5 – baa, 6 - baaa 5 (5,a) 7 aaabbabaabaaabab ba b 0 – “”, 1- a, 2 – aa, 3 – b, 4 – ba,

5 – baa, 6 – baaa, 7 - bab 4 (4,b)

Bảng 3.6: Quá trình nén xâu “ aaabbabaabaaabab” bằng thuật toán LZ78

Quá trình giải nén

TT Cặp mã đọc vào

Ghi

ra Từ điển Xâu kết quả

1 (0,a) a 0 – “”, 1 - a a

2 (1,a) aa 0 – “”, 1 – a, 2 – aa aaa

3 (0,b) b 0 – “”, 1 – a, 2 – aa, 3 – b aaab 4 (3,a) ba 0 – “”, 1 – a, 2 – aa, 3 – b, 4 - ba aaabba 5 (4,a) baa 0 – “”, 1 – a, 2 – aa, 3 – b, 4 – ba, 5 –

baa aaabbabaa

6 (5,a) baaa 0 – “”, 1 – a, 2 – aa, 3 – b, 4 – ba, 5 –

baa, 6 – baaa aaabbabaabaaa

7 (4,b) bab 0 – “”, 1 – a, 2 – aa, 3 – b, 4 – ba, 5 –

baa, 6 – baaa, 7 - bab aaabbabaabaaabab

Bảng 3.7: Quá trình nén bằng thuật toán LZ78 bản mã “(0,a)(1,a)(0,b)(3,a)(4,a)(5,a)(4,b)”

Kết quả giải mã ta đƣợc: aaabbabaabaaabab

Thuật toán này có ƣu điểm là mã hoá và giải mã tƣơng đối nhanh tuy nhiên vẫn còn hạn chế trong hiệu quả nén (đối với file văn bản đạt trung bình 40%, chỉ đạt hiệu quả cao khi nén các file lớn).

3/. Thuật toán LZW

LZW đƣợc đặt tên từ những ngƣời tạo ra nó A.Lempel, J.Ziv và Terry A.Welch. Đây là phƣơng pháp nén file mới nhất, hiệu quả nén trung bình là 50%. Nó không chỉ đƣợc sử dụng cho file .doc, .txt mà còn cho cả file hình ảnh nhƣ file .gif…

Điểm khác biệt giữa LZ78 và LZW trong nguyên lý nén.

Khởi tạo từ điển bao gồm tất cả các kí tự trong bảng chữ cái ban đầu. Kí tự cuối cùng của đoạn copy này là kí tự đầu của đoạn copy sau. Bản mã chỉ là chỉ số các đoạn copy chứ không có các kí tự nữa.

Quá trình nén

Thuật toán nén (adsbygoogle = window.adsbygoogle || []).push({});

Bước 1: Khởi tạo từ điển gồm các kí tự trong bảng chữ cái của văn bản xuất hiện trong văn bản đƣợc đánh chỉ số từ 0. Xâu trung gian P rỗng.

Bước 2: Đọc kí tự tiếp theo trong văn bản vào C.

Bước 3: Xâu P + C đã có trong từ điển chƣa? Nếu có thì P ← P + C

Nếu không thì:

i. Ghi ra bản mã chỉ số của P trong từ điển. ii. Thêm xâu P + C vào từ điển.

iii. P ← C (lúc này P chứa một kí tự). Bƣớc 4: Còn kí tự nào trong văn bản không?

Nếu có thì quay lại bƣớc 2. Nếu không thì:

i. Ghi ra bản mã chỉ số của P trong từ điển. ii. Kết thúc.

Sơ đồ nén

Hình 3.13: Sơ đồ nén dữ liệu thuật toán LZW

Bắt đầu

Khởi tạo từ điển. Xâu trung gian P rỗng

Đọc kí tự tiếp theo vào C

P + C đã có

trong từ điển? P ← P + C

W ← chỉ số của P trong từ điển

Ghi ra bản mã W

Cập nhật P + C vào từ điển

P ← C

Còn kí tự trong văn bản?

W ← chỉ số của P trong từ điển

Kết thúc Ghi ra bản mã W Đúng Đúng Sai Sai

Quá trình giải nén

Gọi cW là từ mã đang đƣợc giải mã. Ký hiệu .cW là nội dung đoạn copy có ký hiệu cW trong từ điển.

Gọi pW là từ mã đứng trƣớc từ mã hiện thời trong bản mã. Ký hiệu .pW là nội dung đoạn copy có ký hiệu pW trong từ điển.

Nguyên lý của giải mã nhƣ sau:

Tại thời điểm khởi tạo thì từ điển giống nhƣ lúc mã hoá.

Tại thời điểm bất kỳ trong quá khứ, khi từ điển chứa vài đoạn copy dài hơn. Ghi nhớ từ mã trƣớc pW.

Đọc từ mã hiện thời cW từ bản mã. Đƣa ra đoạn copy .cW.

Cộng đoạn copy .pW với kí tự đầu tiên của đoạn copy .cW và thêm vào từ điển. (adsbygoogle = window.adsbygoogle || []).push({});

Hai từ mã pW và cW liên tiếp nhau trong bản mã, khi đó kí tự cuối cùng của .pW là kí tự đầu tiên của .cW.

Chú ý: trong quá trình nén thuật toán thêm một đoạn copy vào từ điển trƣớc khi toàn bộ đoạn đó đƣợc nén, đó là kí tự cuối của đoạn copy (đƣợc xử lý ở trong đoạn copy sau). Nếu vì một lý do nào đó mà trình nén sử dụng ngay lập tức đoạn copy này thì khi giải nén sẽ có vấn đề là gặp phải mã của một đoạn copy mà nó lại chƣa xuất hiện trong từ điển (còn thiếu một kí tự cuối cùng là kí tự đầu tiên của đoạn copy đƣợc giải mã tiếp theo).

Ví dụ:

Giả sử đoạn copy IWOMBAT đã có trong từ điển với chỉ số là 300 (tức là mã của đoạn copy này là 300), còn đoạn copy IWOMBATI thì chƣa có trong từ điển.

Khi gặp đoạn văn bản IWOMBATIWOMBATI trình nén sẽ đƣa ra mã là 300 và thêm vào từ điển đoạn copy IWOMBATI, giả sử với mã là 400. Và sử dụng ngay mã 400 cho đoạn copy tiếp theo. Khi đó cả đoạn văn bản trên có mã là <300><400>.

Xét quá trình giải nén: sau khi thay <300> bằng đoạn copy IWOMBAT thì trình giải nén gặp mã <400>. Nhƣng khi đó trong từ điển của trình giải nén chƣa có đoạn copy IWOMBATI vì còn thiếu chữ I ở cuối.

Cho nên trong nguyên lý giải nén việc đƣa ra đoạn copy .cW không phải lúc nào cũng thực hiện đƣợc. Tuy nhiên, nó cũng chỉ không thành công trong trƣờng hợp gặp đoạn văn bản có dạng nhƣ trong ví dụ này. Vì để đƣa ra đoạn copy của cW trong từ điển chúng ta cũng chỉ thiếu có một kí tự cuối và kí tự này xuất hiện ở đầu của đoạn copy .cW. Do đó, trong trƣờng hợp này thì đoạn .pW đƣợc mở rộng bằng thêm kí tự đầu tiên của nó, xâu kết quả đƣợc ra và thêm nó vào từ điển.

Thuật toán giải nén

Bước 1: Khởi tạo từ điển ban đầu gồm các kí tự trong bảng chữ cái của văn bản xuất hiện trong văn bản, đƣợc đánh chỉ số từ 0.

Bước 2: cW ← từ mã đầu tiên trong bản mã.

Bước 3: Ghi đoạn copy .cW ra bản giải mã.

Bước 4: pW ← cW.

Bước 5: cW ← từ mã tiếp theo trong bản mã.

Bước 6: Đoạn copy .cW có trong từ điển không? Nếu có thì

i. Ghi đoạn copy .cW ra bản giải mã. ii. p ← .pW

iii. c ← kí tự đầu tiên của đoạn copy .cW iv. Thêm đoạn copy p + c vào từ điển.

Nếu không thì i. p ← .pW

ii. c ← kí tự đầu tiên của đoạn copy .pW

iii. Ghi đoạn copy p + c ra bản giải mã và thêm nó vào từ điển.

Bước 7: Còn từ mã nào trong bản mã không? Nếu có thì quay về bƣớc 4.

Sơ đồ giải nén

cW ← từ mã đầu tiên

Ghi .cW ra bản giải mã

cW ← từ mã tiếp theo

Ghi .cW ra bản giải mã p ← .pW

c ← kí tự đầu tiên của .pW

Ghi p + c ra bản giải mã Cập nhật p + c vào từ điển Bắt đầu

Khởi tạo từ điển.

Đúng

Đúng pW ← cW (adsbygoogle = window.adsbygoogle || []).push({});

.cW đã có trong từ điển?

c ← kí tự đầu tiên của .cW

Cập nhật p + c vào từ điển Sai p ← .pW Còn kí tự trong văn bản? Sai Kết thúc

Ví d:

Cho văn bản aabababaaababb

Quá trình nén

TT Xâu đã xét P C Từ điển Ghi

ra

1 aa a a 0 – a, 1 – b, 2 - aa 0

2 aab a b 0 – a, 1 – b, 2 – aa, 3 - ab 0

3 aaba b a 0 – a, 1 – b, 2 – aa, 3 – ab, 4 - ba 1 4 aababa ab a 0 – a, 1 – b, 2 – aa, 3 – ab, 4 – ba, 5 -

aba 3

5 aabababaa aba a 0 – a, 1 – b, 2 – aa, 3 – ab, 4 – ba, 5 –

aba, 6 – abaa 5

6 aabababaaab aa b 0 – a, 1 – b, 2 – aa, 3 – ab, 4 – ba, 5 –

aba, 6 – abaa, 7 – aab 2

7 aabababaaabab ba b 0 – a, 1 – b, 2 – aa, 3 – ab, 4 – ba, 5 – aba, 6 – abaa, 7 – aab, 8 – bab 4 8 aabababaaababb b b 0 – a, 1 – b, 2 – aa, 3 – ab, 4 – ba, 5 –

aba, 6 – abaa, 7 – aab, 8 – bab, 9 – bb 1 9 aabababaaababb 0 – a, 1 – b, 2 – aa, 3 – ab, 4 – ba, 5 –

aba, 6 – abaa, 7 – aab, 8 – bab, 9 – bb 1

Bảng 3.8: Quá trình nén xâu “aabababaaababb” bằng thuật toán LZW

Quá trình giải nén TT pW cW Từ điển Ghi ra 0 0 0 – a, 1 – b a 1 0 0 0 – a, 1 – b, 2 – aa a 2 0 1 0 – a, 1 – b, 2 – aa, 3 - ab b 3 1 3 0 – a, 1 – b, 2 – aa, 3 – ab, 4 – ba ab 4 3 5 0 – a, 1 – b, 2 – aa, 3 – ab, 4 – ba, 5 – aba aba 5 5 2 0 – a, 1 – b, 2 – aa, 3 – ab, 4 – ba, 5 – aba, 6 – abaa aa 6 2 4 0 – a, 1 – b, 2 – aa, 3 – ab, 4 – ba, 5 – aba, 6 –

abaa, 7 – aab ba

7 4 1 0 – a, 1 – b, 2 – aa, 3 – ab, 4 – ba, 5 – aba, 6 –

abaa, 7 – aab, 8 – bab b

8 1 1 0 – a, 1 – b, 2 – aa, 3 – ab, 4 – ba, 5 – aba, 6 –

abaa, 7 – aab, 8 – bab, 9 - bb b

Bảng 3.9: Quá trình giải nén bản mã “001352411” theo thuật toán LZW

Kết quả thu đƣơc là aabababaaababb.

Nhận xét

Phƣơng pháp này rất thông dụng trong thực tiễn, thuận lợi hơn so với LZ78 do hiệu quả nén cao hơn (trung bình khoảng 70% đối với file văn bản). Cải tiến hơn về kích thƣớc từ mã (phụ thuộc vào kích thƣớc từ điển). (adsbygoogle = window.adsbygoogle || []).push({});

Chương 4: PHỐI HỢP HAI PHƢƠNG PHÁP NÉN VÀ MÃ HOÁ THÔNG TIN

Chƣơng 2, Chƣơng 3 đã trình bày một số phƣơng pháp mã hoá và nén dữ liệu. Tuy nhiên, nếu tập tin chỉ đƣợc nén chƣa đảm bảo tính bảo mật. Ngƣợc lại nếu tệp tin chỉ đƣợc mã hoá sẽ tốn thời gian mã hoá, tăng không gian lƣu trữ, tốn băng thông truyền tải. Trong Chƣơng 4 sẽ trình bày quá trình phối hợp 2 quá trình nén và mã hoá thông tin đồng thời giới thiệu chƣơng trình thử nghiệm sự kết hợp này.

Một phần của tài liệu Nghiên cứu phối hợp hai phương pháp nén và mã hóa thông tin (Trang 66 - 80)