Một thuật toán nén hiệu quả cho các chuỗi văn bản ngắn [đã đóng]


126

Tôi đang tìm kiếm một thuật toán để nén các chuỗi văn bản nhỏ: 50-1000 byte (tức là các URL). Thuật toán nào hoạt động tốt nhất cho việc này?


1
Nơi nào bạn muốn sử dụng các chuỗi nén?
Gumbo

1
Đây có phải là hướng tới tinyurlshoặc một cái gì đó để làm với không gian lưu trữ?
nik

6
Tôi quan tâm đến một thuật toán để nén URL, tỷ lệ nén tốt nhất là quan trọng hơn khi chạy chi phí. Không quan tâm đến các dịch vụ trực tuyến như tinyurls hoặc tr.im. Tôi đang tìm kiếm một thuật toán không phải là một dịch vụ. Đừng nghĩ bất kỳ thông tin nào khác có thể hữu ích ...
Vasily Korolev

3
@Gumbo: "Thuật toán nén văn bản cho các chuỗi ngắn" là đủ để tìm các thuật toán, tại sao bạn lại quan tâm đến việc biết chúng dùng để làm gì? Tôi chắc chắn OP sẽ có thể tìm thấy thứ mà anh ấy muốn.
Dervin Thunk

7
@Vasily, một gợi ý nhỏ: Bất cứ khi nào bạn đặt câu hỏi về SO dưới dạng " XYZ tốt nhất là gì?", Câu hỏi của bạn gần như bị ràng buộc để nhận phiếu bầu vì đóng cửa vì yêu cầu tốt nhất có thể dẫn đến sản phẩm không cần thiết so sánh, hoặc trong trường hợp xấu nhất, thậm chí là chiến tranh lửa. (Thường chỉ cần một thay đổi rất nhỏ để tránh điều đó: Nếu bạn hỏi cùng một câu hỏi như: "Vui lòng đề xuất XYZ.", Bạn sẽ không nhận được nhiều phiếu kết thúc, mặc dù về cơ bản đó là cùng một câu hỏi!)
stakx - không còn đóng góp

Câu trả lời:


62

Kiểm tra Smaz :

Smaz là một thư viện nén đơn giản phù hợp để nén các chuỗi rất ngắn.


17
Xem github.com/antirez/smaz/blob/master/smaz.c - đây là một biến thể của mã hóa, không nén mỗi se (ít nhất là không hoàn toàn). Ông sử dụng một từ điển tĩnh và từ điển thư.
Roy Tinker

7
Lưu ý: Đây là dự án của antirez. Ông là một trong những tác giả chính của Redis và có uy tín rất lớn về việc phát hành mã sản xuất, chất lượng cao.
Homer6

7
Thuật toán smaz được tối ưu hóa cho các văn bản tiếng Anh, do đó không hoạt động tốt cho các chuỗi ngẫu nhiên. Dưới đây là một số mẫu ( string:orig_size:compr_size:space_savings): This is the very end of it.:27:13:52%, Lorem ipsum dolor sit amet:26:19:27%, Llanfairpwllgwyngyll:20:17:15%, aaaaaaaaaaaaa:13:13:0%, 2BTWm6WcK9AqTU:14:20:-43%,XXX:3:5:-67%
mykhal

4
Ngoài ra hãy xem mức nén thấp hơn nhưng thuật toán nhanh shoco ed-von-schleck.github.io/shoco
Dickey Singh

Thêm thư viện của tôi Unishox vào danh sách github.com/siara-cc/unishox . Nó hoạt động tốt hơn Smaz và Shoco và hỗ trợ nén các chuỗi UTF-8.
arun

28

Huffman có một chi phí tĩnh, bảng Huffman, vì vậy tôi không đồng ý đó là một lựa chọn tốt.

Có những phiên bản thích ứng loại bỏ điều này, nhưng tốc độ nén có thể bị ảnh hưởng. Trên thực tế, câu hỏi bạn nên đặt ra là "thuật toán nào để nén các chuỗi văn bản với các đặc điểm này". Ví dụ, nếu dự kiến ​​lặp lại dài, Mã hóa Run-Lengh đơn giản có thể là đủ. Nếu bạn có thể đảm bảo rằng chỉ có các từ tiếng Anh, dấu cách, dấu chấm câu và các chữ số không thường xuyên sẽ xuất hiện, thì Huffman với bảng Huffman được xác định trước có thể mang lại kết quả tốt.

Nói chung, các thuật toán của gia đình Lempel-Ziv có khả năng nén và hiệu năng rất tốt và các thư viện cho chúng rất nhiều. Tôi sẽ đi với điều đó.

Với thông tin rằng những gì đang được nén là URL, thì tôi khuyên bạn nên trước khi nén (với bất kỳ thuật toán nào có sẵn dễ dàng), bạn CODIFY chúng. Các URL tuân theo các mẫu được xác định rõ và một số phần của nó có khả năng dự đoán cao. Bằng cách sử dụng kiến ​​thức này, bạn có thể mã hóa các URL thành một cái gì đó nhỏ hơn để bắt đầu và những ý tưởng đằng sau mã hóa Huffman có thể giúp bạn ở đây.

Ví dụ: dịch URL thành luồng bit, bạn có thể thay thế "http" bằng bit 1 và bất cứ thứ gì khác bằng bit "0" theo sau là Procotol thực tế (hoặc sử dụng bảng để nhận các giao thức phổ biến khác, như https, ftp, tập tin). ": //" có thể được loại bỏ hoàn toàn, miễn là bạn có thể đánh dấu sự kết thúc của giao thức. V.v. Hãy đọc về định dạng URL và suy nghĩ về cách chúng có thể được mã hóa để chiếm ít không gian hơn.


4
Không phải nếu bảng huffman giống nhau cho tất cả các tệp, điều này sẽ có ý nghĩa nếu các tệp hoàn toàn giống nhau.
vây

1
Nếu bạn có nhiều tệp nhỏ, tương tự, nhỏ, bạn đang làm sai tất cả. Đầu tiên, nối tất cả chúng (giống như tar), và sau đó nén nó. Bạn sẽ có được nén tốt hơn và vấn đề không còn là "50-1000 byte".
Daniel C. Sobral

8
@Daniel: phụ thuộc vào việc bạn có muốn truy cập ngẫu nhiên vào dữ liệu nén hay không. Nén tất cả lại với nhau ngăn chặn điều đó với hầu hết các hệ thống nén.
Steve Jessop

22

Tôi không có mã trong tay, nhưng tôi luôn thích cách tiếp cận xây dựng bảng tra cứu 2D có kích thước 256 * 256 ký tự ( RFC 1978 , Giao thức nén dự đoán PPP ). Để nén một chuỗi, bạn lặp qua từng char và sử dụng bảng tra cứu để lấy char tiếp theo 'dự đoán' bằng cách sử dụng char hiện tại và trước đó làm chỉ mục vào bảng. Nếu có một trận đấu bạn viết 1 bit đơn, nếu không hãy viết 0, char và cập nhật bảng tra cứu với char hiện tại. Cách tiếp cận này về cơ bản duy trì một bảng tra cứu động (và thô) của nhân vật tiếp theo có thể xảy ra nhất trong luồng dữ liệu.

Bạn có thể bắt đầu với một bảng tra cứu bằng 0, nhưng thật ra nó hoạt động tốt nhất trên các chuỗi rất ngắn nếu nó được khởi tạo với ký tự có khả năng nhất cho mỗi cặp ký tự, ví dụ, đối với ngôn ngữ tiếng Anh. Miễn là bảng tra cứu ban đầu giống nhau để nén và giải nén, bạn không cần phải phát nó vào dữ liệu nén.

Thuật toán này không cho tỷ lệ nén tuyệt vời, nhưng nó cực kỳ tiết kiệm với tài nguyên bộ nhớ và CPU và cũng có thể hoạt động trên một luồng dữ liệu liên tục - bộ giải nén duy trì bản sao của bảng tra cứu khi giải nén, do đó bảng tra cứu điều chỉnh loại dữ liệu được nén.


Nhưng làm thế nào người dự đoán sẽ hành xử với câu tiếng Anh bình thường? Ví dụ đã cho có sự dư thừa rất mạnh và mức tăng là tối thiểu.
Thủy thủ Danubian

Bảng tra cứu 256 * 256 không có âm thanh "vô cùng tiết kiệm với bộ nhớ" ...!
MikeW

@MikeW Vâng, 65 kilobyte.
redcalx

@redcalx Nếu đã là 65 byte thì tôi có thể đã đồng ý!
MikeW

11

Bất kỳ thuật toán / thư viện nào hỗ trợ từ điển đặt trước, ví dụ zlib .

Bằng cách này, bạn có thể xử lý trình nén với cùng loại văn bản có khả năng xuất hiện trong đầu vào. Nếu các tệp tương tự nhau theo một cách nào đó (ví dụ: tất cả các URL, tất cả các chương trình C, tất cả các bài đăng StackOverflow, tất cả các bản vẽ nghệ thuật ASCII) thì các chuỗi con nhất định sẽ xuất hiện trong hầu hết hoặc tất cả các tệp đầu vào.

Mọi thuật toán nén sẽ tiết kiệm dung lượng nếu cùng một chuỗi con được lặp lại nhiều lần trong một tệp đầu vào (ví dụ: "the" trong văn bản tiếng Anh hoặc "int" trong mã C.)

Nhưng trong trường hợp URL, một số chuỗi nhất định (ví dụ: " http: // www .", ".Com", ".html", ".aspx" thường sẽ xuất hiện một lần trong mỗi tệp đầu vào. Vì vậy, bạn cần chia sẻ chúng giữa các tệp. bằng cách nào đó thay vì có một lần xuất hiện nén trên mỗi tệp. Đặt chúng vào một từ điển đặt sẵn sẽ đạt được điều này.


2
Mẹo sử dụng từ điển tùy chỉnh: stackoverflow.com/questions/2011653
Trenton

4

Mã hóa Huffman thường hoạt động tốt cho việc này.


4
Đây không phải là một câu trả lời chỉ liên kết; không có liên kết, nó vẫn là một câu trả lời hợp lệ.
SL Barth - Phục hồi Monica

.. và vẫn không phải là một câu trả lời tốt. (Không đủ thông tin liên quan được đưa vào.)
user2864740

4

Nếu bạn đang nói về việc thực sự nén văn bản không chỉ rút ngắn thì Deflate / gzip (trình bao bọc xung quanh gzip), zip hoạt động tốt cho các tệp và văn bản nhỏ hơn. Các thuật toán khác có hiệu quả cao cho các tệp lớn hơn như bzip2, v.v.

Wikipedia có một danh sách thời gian nén. (tìm kiếm để so sánh hiệu quả)

Name       | Text         | Binaries      | Raw images
-----------+--------------+---------------+-------------
7-zip      | 19% in 18.8s | 27% in  59.6s | 50% in 36.4s
bzip2      | 20% in  4.7s | 37% in  32.8s | 51% in 20.0s
rar (2.01) | 23% in 30.0s | 36% in 275.4s | 58% in 52.7s
advzip     | 24% in 21.1s | 37% in  70.6s | 57& in 41.6s
gzip       | 25% in  4.2s | 39% in  23.1s | 60% in  5.4s
zip        | 25% in  4.3s | 39% in  23.3s | 60% in  5.7s

6
Anh ta muốn nén văn bản và không tập tin.
Gumbo

3
Bạn có thể nén văn bản và nhị phân với các thuật toán này. Trong thực tế, chúng tôi sử dụng giảm phát trong một hệ thống cms chạy trong python.
Ryan Christensen

Một ví dụ trong C # sử dụng gzip cho chuỗi có tại đây: csharphelp.com/archives4/archive689.html
Ryan Christensen

mô-đun zlib trong python để nén chuỗi: python.org/doc/2.5.2/lib/module-zlib.html
Ryan Christensen

3
gzip (và zlib) sử dụng giảm phát và thêm chi phí đóng gói / đóng khung .. giảm phát trực tiếp / LZ77 (chi phí từ điển và hiệu quả vẫn phụ thuộc vào việc thực hiện như vậy và cài đặt) có thể làm giảm chi phí hòa vốn. Tất nhiên, đây là chuỗi "ngắn" trong hàng chục đến hàng trăm ký tự (vẫn nên có một chút để chỉ ra "đã bị nén" này chưa? Để tránh mở rộng dữ liệu). Chi phí lớn hơn không quan trọng .. khi văn bản tăng. Các số được đăng ở đây dường như là dành cho các tệp văn bản lớn (nhiều giây để chạy!), Trong khi OP yêu cầu 50-1000 biểu đồ - so sánh rất nhỏ .
dùng2864740

2

Bạn có thể muốn xem sơ đồ nén tiêu chuẩn cho Unicode .

SQL Server 2008 R2 sử dụng nội bộ và có thể đạt được mức nén lên tới 50%.


SCSU 'nén' Unicode không phải tiếng Anh trong bảng mã UTF-16 / MB. Nếu Unicode / plain-old-ASCII dựa trên tiếng Anh, UTF-8 cũng 'nén' 50% UTF-16 ..
user2864740
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.