Thuật toán LZ7 7 LZ78

Một phần của tài liệu MÃ HOÁ NÉN DỮ LIỆU VÀ MÃ HOÁ CÓ KHẢ NĂNG PHÁT HIỆN SAI VÀ SỬA SAI (Trang 56 - 62)

Năm 1977 - 1978, Jacov Ziv và Abraham Lempel ựã mô tả một cặp phương pháp nén dữ liệu sử dụng kết hợp từ ựiển. Hai phương pháp này ựã mở ựầu cho một kĩ thuật nén mới, trong ựó sử dụng phương pháp nén từựiển làm cơ sở.

3.2.2.1. Thut toán LZ77

Trong phương pháp nén LZ77, người ta dùng hai phần bộ nhớ. đó là cửa sổ trượt (window) và vùng ựệm (buffer). Kắch cỡ bình thường của cửa sổ là một vài ngàn kắ tự do ta quy ựịnh, vùng ựệm nói chung nhỏ hơn rất nhiều, có thể từ 10 ựến 100 kắ tự. Thuật toán này luôn luôn tìm những nội dung phù hợp của vùng ựệm thành một xâu trong từựiển.

Vắ d:

for (i = 0; i< max - 1; i++)\r for (j = i + 1; j < max ; j ++) \r Cửa sổ trượt Vùng ựệm

Hình vẽ này mô tả một cửa sổ trượt (gồm 48 kắ tự) và vùng ựệm (gồm 16 kắ tự). Thuật toán LZ77 theo cách hiểu thông thường ựưa ra những dấu hiệu

liên tiếp. Mỗi dấu hiệu bao gồm ba nhóm dữ liệu khác nhau xác ựịnh chiều dài thay ựổi của nhóm từ trong vùng ựệm. Ba nhóm dữ liệu là: 1- địa chỉ của nhóm từ trong cửa sổ trượt; 2 - độ dài của nhóm từ; 3 - Kắ tự ựầu tiên trong vùng ựệm theo sau nhóm từ.

Trong vắ dụ trên, vùng ựệm bao gồm nhóm từ Ộ< max ; j ++) \rỢ, ta thấy Ộ< maxỢ ựược tìm thấy tại vị trắ 14 trong cửa sổ trượt. Nó gồm 4 vị trắ bắt ựầu từ vị trắ thứ nhất trong vùng ựệm, kắ tựựầu tiên theo sau nó có mặt trong vùng

ựệm là kắ tự trắng (Space). Vì vậy, nhóm từ này ựược mã hoá là Ộ14,4,Ỗ ỔỢ. Chương trình nén thực hiện thuật toán LZ77 phát ra dấu hiệu ựầu tiên, sau ựó thay ựổi cửa sổ trượt bởi năm kắ tự là ựộ dài nhóm từ ựược mã hoá (bao gồm cả kắ tự theo sau). Năm kắ tự mới sau ựó ựược ựọc vào vùng ựệm và quá trình lặp lại.

(i = 0; i< max - 1; i++)\r for (j = i + 1; j<max ; j ++) \r a{ I Cửa sổ trượt Vùng ựệm

Biểu hiện tiếp theo ựược ựưa ra bằng thuật toán nén sẽ mã hoá nhóm từ

Ộ;j+Ợ (bao gồm cả kắ tự theo sau) thành Ộ40,2,Ỗ+ỖỢ. Cú pháp của dấu hiệu này cho phép mã hoá của những nhóm từ không có mặt trong cửa sổ trượt. Nếu vùng ựệm chỉ ra kắ tự không phù hợp, vắ dụ nó có thể mã hoá một kắ tựựơn lẻ

tại một thời ựiểm không có mặt trong cửa sổ trượt như là một nhóm từ với ựộ

là 0: Ộ0,0,Ỗ;ỖỢ thì phương pháp này không hiệu quả, vì ựể mã hoá một kắ tự ta cần ba loại thông tin. Nhưng có thể cho thấy rằng thuật toán có thể mã hoá mọi loại xâu kắ tự.

Việc thực hiện của thuật toán nén rõ ràng ựơn giản, nó cho phép xem xét xuyên suốt toàn bộ cửa sổ trượt với sự phù hợp tối ựa, mã hoá sau ựó chuyển

ựổi. Thuật toán giải nén của LZ77 cũng ựơn giản như thuật toán nén. Bởi vì nó không phải tiến hành những so sánh, nó ựọc những dấu hiệu của ựầu vào,

ựưa ra những nhóm từ xác ựịnh, ựưa ra những kắ tựựi theo, chuyển ựổi và lặp lại, nó duy trì cửa sổ nhưng nó không làm việc so sánh.

Một ảnh hưởng tắch cực của phương pháp giải nén là nó có thể sử dụng nhóm từ chưa ựược mã hoá ựể mã nhóm từựã có. Trong một file có 100 kắ tự

ỘAỢ liên tục, vắ dụ, chúng ta có thể mã hoá kắ tự A ựầu tiên là (0,0,ỖAỖ). Cửa sổ sẽ như hình dưới:

ỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖA AAAAAAAAAA Chúng ta có thể mã hoá 9 kắ tự A là (40,9,ỖAỖ) ở ựây 40 là kắch cỡ của cửa sổ trượt. Nó dường như là sử dụng một nhóm từ có 9 kắ tự. Mặc dù ta có thể thấy 10 kắ tự trong nhóm từ hiển thị ở vùng ựệm, nhưng không có mặt trong cửa sổ trượt. Khi giải nén nhận ựược dấu hiệu (40,9,ỖAỖ). Vùng ựệm sẽ

như hình hưới:

ỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖA

Nhưng nếu xem xét thuật toán giải nén, ta sẽ thấy ựược cách thức tiến trình giải nén có tiến hành thủ thuật này. Sau khi kắ tựựầu tiên ựược sao chép, vùng ựệm sẽ như hình dưới:

ỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖA A

Tiếp sau ựó qua vòng lặp, 9 kắ tự A sẽ ựược sao chép, cho dù chúng không có trong cửa sổ khi bắt ựầu tiến hành giải mã. Sau khi việc sao chép ựã hoàn tất, kắ tựựơn tiếp theo sẽựọc vào, vùng ựệm ựã sẵn sàng chuyển ựổi như

hình dưới:

ỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖỖA AAAAAAAAAA

điều này chứng minh ựiểm mạnh của phương pháp nén LZ77: thắch ứng nhanh chóng thông tin ựầu vào. Chẳng hạn, với vắ dụ trên, LZ77 mã hoá một nhóm gồm 10 kắ tự khi ỘtừựiểnỢ của nó chỉ chứa một kắ tựựơn.

Tuy nhiên, LZ77 có nhược ựiểm: Khi mã hoá nó phải so sánh chuỗi kắ tự (adsbygoogle = window.adsbygoogle || []).push({});

trong vùng ựệm với tất cả vị trắ cửa sổ trượt. Vì muốn tăng ựộ nén ta phải tăng kắch cỡ của cửa sổ trượt, việc cố ựịnh phần từựiển làm cho thuật toán LZ77 trở thành kém hiệu quả. Nhưng LZ77 có ưu ựiểm là khi giải mã không chịu hậu quả của ảnh hưởng trên, nó chỉ sao lại những nhóm từ cho nên việc giải mã có tốc ựộ cao hơn. Thậm chắ phương pháp giải nén LZ77 không ảnh hưởng bởi việc tăng kắch cỡ của cửa sổ trượt lẫn vùng ựệm.

Nếu nhóm từ không tìm thấy trong từựiển thì chuyện gì xảy ra? Lúc ựó, LZ77 không còn tỏ ra hiệu quả nữa bởi khi gặp từ không có trong từ ựiển

Vị trắ xử lắ +i Vùng ựệm

chương trình nén vẫn sử dụng ựúng 3 loại thông tin liên hệ chỉựể mã hoá một kắ tự. Chẳng hạn, ựể mã hoá một kắ tự không có trong từ ựiển phải dùng 4096 byte cho cửa sổ trượt và 16 byte cho vùng ựệm. Việc này cần 12 bit mã hoá vị

trắ trong cửa sổ trượt và 4 bit khác ựể mã hoá ựộ dài của nhóm từ. Khi ựó, ta cần ựến 24 bit ựể mã hoá dấu hiệu (0,0,c), trong khi ta chỉ cần 8 bit ựể mã hoá kắ tựựó. Tập tin nén thậm chắ còn lớn hơn tập tin trước khi nén, vì vậy, cần có cách cải tiến LZ77.

3.2.2.2. Thut toán LZ78

LZ78 ựược cải tiến ựể giúp làm tăng mức ựộ nén của chương trình. LZ78 từ bỏ khái niệm về một cửa sổ trượt, trong LZ78, từ ựiển là một danh sách không có giới hạn của những xâu.

Tương tự LZ77, LZ78 cũng ựưa ra một dãy các nhóm với ý nghĩa tương tự, mỗi nhóm của LZ78 bao gồm một mã chỉ ra chuỗi ựược chọn và một kắ tự

theo sau chuỗi. Không giống như LZ77, chiều dài của chuỗi không ựược xác

ựịnh cho tới khi bộ giải mã biết ựược.

LZ78 không có sẵn một cửa sổ trượt ựể sử dụng như một từ ựiển, nó tạo ra một xâu mới mỗi khi một nhóm ựược ựưa ra và thêm xâu ựó vào từ ựiển. Sau khi xâu ựược thêm vào, nó sẽ sẵn sàng ựể mã hoá bất kì lúc nào sau này chứ không phải chỉựối với vài nghìn kắ tự tiếp theo.

Khi sử dụng thuật toán LZ78, cả hai quá trình nén và giải nén ựều bắt

ựầu với một từựiển gần như rỗng. Theo ựịnh nghĩa, từựiển chỉ có một xâu ựã

ựược mã hoá, ựó là xâu rỗng, mỗi khi một kắ tự ựược ựọc vào, nó sẽ ựược thêm vào chuỗi hiện thời, chừng nào chuỗi hiện thời so khớp với vài cụm từ

trong từựiển, quá trình này vẫn tiếp tục.

Khi chuỗi không ựúng với xâu ựã có trong từựiển, LZ78 sẽựưa ra nhóm và kắ tự. Ta biết rằng chuỗi có sự so sánh trong từựiển cho ựến khi kắ tự cuối cùng ựược ựọc vào. Vì thế, chuỗi hiện tại ựược coi như là sự so khớp cuối cùng cho ựến khi một kắ tự mới ựã ựược thêm vào. Khi ựó LZ78 sẽựưa ra: vị

Nhưng LZ78 không dừng ở ựây, xâu mới gồm có chuỗi có trong từ ựiển và kắ tự mới sẽ ựược thêm vào từ ựiển. Sau này, khi xâu xuất hiện nó có thể ựược sử dụng ựể xây dựng xâu dài hơn.

Theo ựịnh nghĩa, chuỗi rỗng sẽ luôn luôn là xâu 0. đó là nút rỗng trong từ ựiển. Vì vậy, khi chúng ta gặp phải một kắ tự lần ựầu tiên, nó sẽ ựược mã hoá như là một xâu 0 và thêm vào kắ tựựó. Lần sau kắ tự này xuất hiện, nó sẽ ựược mã hoá như là một phần của xâu.

Vắ d:

Bản tin ựọc vào có dạng: ỘDAD DADA DADDY DADOẦỢ

Quá trình mã hoá LZ78 bắt ựầu khi không có xâu nào trong từ ựiển, vì thế kắ tự ựầu tiên nó ựọc ựược từựầu vào ỔDỖ, tạo ra một chuỗi chưa có trong từ ựiển. Việc mã hoá sẽ ựưa ra cặp xâu/ kắ tự, trong trường hợp này là 0 và ỔDỖ.

Giá trựưa ra Kắ tựựưa ra Xâu ựược mã hoá

0 ỔDỖ ỘDỢ 0 ỔAỖ ỘAỢ 1 Ổ Ổ ỘDỢ 1 ỔAỖ ỘDAỢ 4 Ổ Ổ ỘDAỢ 4 ỔDỖ ỘDADỢ 1 ỔYỖ ỘDYỢ 0 Ổ Ổ Ộ Ộ 6 ỔOỖ ỘDADOỢ Bng 3.8. Quá trình mã hoá LZ78

Hai kắ tự ựầu tiên qua bộ mã hoá ỔDỖ và ỔAỖ chưa ựược thấy trước ựó. Mỗi cái sẽựược mã hoá như là một cặp 0 cộng với kắ tự. ỔDỖ ựược thêm vào từựiển như là xâu thứ nhất và ỔAỖ như là xâu thứ hai.

Khi kắ tự thứ 3 là ỔDỖ ựược ựọc vào, nó so khớp với một xâu có trong từ ựiển. Kắ tự Ộ Ợ (kắ tự trắng) ựược ựọc tiếp vào sẽ tạo ra một xâu mới mà chưa có trong từ ựiển. LZ78 sẽ ựưa ra mã một cho chuỗi trước (xâu ỘDỢ) và tiếp theo là kắ tự Ộ Ợ.

Khi tiếp tục mã hoá từ ựiển nhanh chóng xây dựng ựược những xâu dài. Sau khi 19 kắ tự ựã ựược ựọc vào và ựược mã hoá, ta sẽ có bảng từ ựiển sau: 0 Ộ Ợ 1 ỘDỢ 2 ỘAỢ 3 ỘDỢ 4 ỘDAỢ 5 ỘDAỢ 6 ỘDADỢ 7 ỘDYỢ 8 Ộ Ợ 9 ỘDADOỢ Bng 3.9. Bng từựin ca thut toán LZ78 Giống như LZ77, LZ78 có thể tuỳ ý ựặt kắch thước của xâu từ ựiển. Giống như LZ77 trong LZ78 chúng ta phải quan tâm về sự tác ựộng của nó trong hai trường hợp: thứ nhất, chúng ta phải quan tâm ựến số bit dùng trong nhóm ựưa ra ựối với mỗi mã; thứ hai, quan trọng hơn, chúng ta phải xem xét CPU mất bao nhiêu thời gian ựể quản lắ từựiển.

Trên lắ thuyết, LZ78 sẽ nén tốt hơn nếu kắch thước của từựiển càng lớn, nhưng ựiều này chỉựúng khi ựộ dài của dòng văn bản càng lớn.Trên thực tế, những file nhỏ sẽ bịảnh hưởng khi kắch thước mã lớn. (adsbygoogle = window.adsbygoogle || []).push({});

Thực tế khó khăn ựối với LZ78 là việc quản lắ từ ựiển. Nếu chúng ta sử

dụng mã 16 bit ựể chỉ vị trắ của xâu, chúng ta có thể có 65536 xâu khác nhau, bao gồm cả mã rỗng, một xâu có thể rất dài.

Các xâu này ựược lưu trữ bởi một cây, cây này có nút gốc mang mã 0, ựó là xâu rỗng. Mỗi kắ tựựược thêm vào xâu rỗng là một nhánh mới của cây và mỗi xâu ựược tạo ra bằng cách lấy số của nút mới.

Hình 3.3. Cây qun lắ từựin ca LZ78

Cây từựiển ở trên ựược tạo ra sau khi ựã mã hoá 19 kắ tự. Khó khăn lớn nhất khi quản lắ cây là quản lý số lượng các nhánh của mỗi nút. Khi nén file nhị phân với bảng chữ cái 8 bit thì có thể có 256 nhánh. để ựơn giản ta dùng một mảng chỉ số hoặc các con trỏ tại mỗi nút ựểựủ sức ựựng ựược tất cả 256 nút con. Nhưng khi phần lớn các nút không có nhiều con cháu như vậy thì sẽ

tốn rất nhiều bộ nhớ. Khi ựó, các nút con cháu thường ựược tổ chức là một danh sách các chỉ số mà số lượng các chỉ số không nhiều hớn số lượng của các nút con cháu hiện tại. Kĩ thuật này làm cho việc sử dụng bộ nhớ tốt hơn, nhưng lại chậm hơn.

Với một cây như trên thì việc so sánh một xâu với từ ựiển là ựơn giản, chỉ cần dò theo cây, xem xét mỗi nút của cây ựối với mỗi kắ tự trong xâu. Nếu xâu kết thúc tại một nút riêng biệt chúng ta có sự so khớp. Nếu có xâu mà trong khi dò tìm, chúng ta ựã ở nút lá thì xâu chưa có trong cây. Sau khi kắ tự ựã ựược mã hoá, việc thêm nó vào nút lá khá dễ dàng, vấn ựề chỉ thêm chỗ

trống vào danh sách nút con cháu của nó, rồi chèn thêm vào một nút con mới tại nút có ựối sánh gần nhất.

Thuật toán LZ78 nói chung là một thuật toán nén văn bản tốt, có thời gian chạy chương trình tương ựối nhanh, tuy nhiên khả năng tiết kiệm chưa tối ựa, vì vậy Terry Welch ựã cải tiến và ựưa ra giới thiệu thuật toán LZW.

Một phần của tài liệu MÃ HOÁ NÉN DỮ LIỆU VÀ MÃ HOÁ CÓ KHẢ NĂNG PHÁT HIỆN SAI VÀ SỬA SAI (Trang 56 - 62)