Kısa metin dizeleri için etkili bir sıkıştırma algoritması [kapalı]


126

Küçük metin dizelerini sıkıştırmak için bir algoritma arıyorum: 50-1000 bayt (yani URL'ler). Bunun için hangi algoritma en iyi şekilde çalışır?


1
Bu sıkıştırılmış dizeleri nerede kullanmak istersiniz?
Gumbo

1
Bu tinyurlsdepolama alanına doğru gidiyor mu yoksa bununla ilgili bir şey mi?
nik

6
URL'leri sıkıştırmak için bir algoritma ile ilgileniyorum, en iyi sıkıştırma oranı çalıştırma maliyetinden daha önemlidir. Tinyurls veya tr.im gibi çevrimiçi hizmetlerle ilgilenmiyorum. Hizmet değil bir algoritma arıyorum. Başka herhangi bir
bilginin

3
@Gumbo: Algos bulmak için "Kısa dizeler için metin sıkıştırma algoritmaları" yeterli, neden bunların ne işe yaradığını bilmekle bu kadar ilgileniyorsunuz? Eminim OP istediğini yapan kişiyi bulacaktır.
Dervin Thunk

7
@Vasily, küçük ipucu: "nedir, şeklinde SO üzerinde bir soruyu soruyorsun zaman iyi ? XYZ", sorunuz neredeyse iyi soran çünkü kapatılması için oy almak için bağlı olduğu olabilecek gereksiz ürüne yol karşılaştırmalar veya en kötü durumda, alev savaşları bile. (Bundan kaçınmak için genellikle çok küçük bir değişiklik gerekir: "Lütfen bir XYZ önerin." Gibi aynı soruyu
sorarsanız

Yanıtlar:


62

Smaz'a göz atın :

Smaz, çok kısa dizeleri sıkıştırmak için uygun basit bir sıkıştırma kitaplığıdır.


17
Bkz. Github.com/antirez/smaz/blob/master/smaz.c - bu, kendi başına sıkıştırma değil (en azından tamamen değil) bir kodlama çeşididir. Statik bir kelime ve harf sözlüğü kullanıyor.
Roy Tinker

7
Not: Bu antirez'in projesidir. Redis'in başlıca yazarlarından biridir ve yüksek kaliteli üretim kodu yayınlama konusunda çok güçlü bir üne sahiptir.
Homer6

7
Smaz algoritması İngilizce metinler için optimize edilmiştir, bu nedenle rastgele diziler için iyi çalışmaz. İşte bazı örnekler (şunlardır 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
Ayrıca daha düşük bir sıkıştırmaya ama hızlı bir algoritmaya göz atın
Dickey Singh

Kitaplığım Unishox'u github.com/siara-cc/unishox listesine ekleyin . Smaz ve Shoco'dan daha iyi performans gösterir ve UTF-8 dizelerinin sıkıştırılmasını destekler.
arun

28

Huffman'ın Huffman masasının statik bir maliyeti var, bu yüzden bunun iyi bir seçim olduğuna katılmıyorum.

Bunu ortadan kaldıran uyarlanabilir sürümler vardır, ancak sıkıştırma oranı düşebilir. Aslında sormanız gereken soru, "bu özelliklere sahip metin dizelerini hangi algoritmanın sıkıştıracağıdır". Örneğin, uzun tekrarlar bekleniyorsa, basit Run-Lengh Encoding yeterli olabilir. Yalnızca İngilizce kelimelerin, boşlukların, noktalama işaretlerinin ve ara sıra rakamların bulunacağını garanti edebilirseniz, önceden tanımlanmış bir Huffman tablosu olan Huffman iyi sonuçlar verebilir.

Genel olarak, Lempel-Ziv ailesinin algoritmaları çok iyi sıkıştırma ve performansa sahiptir ve bunlar için bol miktarda kitaplık vardır. Ben onunla giderdim.

Sıkıştırılanın URL'ler olduğu bilgisiyle, sıkıştırmadan önce (hangi algoritma kolayca mevcutsa) onları KODLAYINIZ. URL'ler iyi tanımlanmış kalıpları izler ve bazı kısımları son derece tahmin edilebilirdir. Bu bilgiden yararlanarak, URL'leri başlangıçta daha küçük bir şeye kodlayabilirsiniz ve Huffman kodlamasının arkasındaki fikirler size burada yardımcı olabilir.

Örneğin, URL'yi bir bit akışına çevirirken, "http" yi bit 1 ile ve diğer her şeyi "0" biti ve ardından gerçek procotol ile değiştirebilirsiniz (veya https gibi diğer yaygın protokolleri almak için bir tablo kullanabilirsiniz. ftp, dosya). Protokolün sonunu işaretleyebildiğiniz sürece, ": //" tamamen kaldırılabilir. Vb URL formatı hakkında bilgi edinin ve daha az yer kaplamak için nasıl kodlanabileceklerini düşünün.


4
Huffman tablosu tüm dosyalar için aynı değilse, bu, dosyaların hepsi birbirine benziyorsa mantıklı olacaktır.
finnw

1
Çok sayıda benzer, küçük dosyanız varsa, hepsini yanlış yapıyorsunuz demektir. Önce hepsini birleştirin (katranın yaptığı gibi) ve sonra onu sıkıştırın. Daha iyi sıkıştırma elde edersiniz ve sorun "50-1000 bayt" olmaktan çıkar.
Daniel C. Sobral

8
@Daniel: sıkıştırılmış verilere rastgele erişim isteyip istemediğinize bağlıdır. Hepsini birlikte sıkıştırmak çoğu sıkıştırma sisteminde bunu önler.
Steve Jessop

22

Elimde bir kod yok, ancak 256 * 256 karakter boyutunda bir 2D arama tablosu oluşturma yaklaşımını her zaman sevmişimdir ( RFC 1978 , PPP Predictor Compression Protocol ). Bir dizeyi sıkıştırmak için, her bir karakterin üzerinden dönersiniz ve geçerli ve önceki karakterleri tabloya dizinler olarak kullanarak 'tahmin edilen' sonraki karakteri almak için arama tablosunu kullanın. Bir eşleşme varsa tek bir 1 bit yazarsınız, aksi takdirde bir 0, karakter yazarsınız ve arama tablosunu geçerli karakterle güncellersiniz. Bu yaklaşım temelde veri akışındaki en olası sonraki karakterin dinamik (ve ham) bir arama tablosunu korur.

Sıfırlanmış bir arama tablosu ile başlayabilirsiniz, ancak en iyi sonucu, her karakter çifti için, örneğin İngilizce için en olası karakterle başlatılmışsa, çok kısa dizelerde en iyi şekilde çalışır. İlk arama tablosu sıkıştırma ve açma için aynı olduğu sürece, bunu sıkıştırılmış verilere yaymanıza gerek yoktur.

Bu algoritma mükemmel bir sıkıştırma oranı sağlamaz, ancak bellek ve CPU kaynakları açısından inanılmaz derecede tutumludur ve sürekli bir veri akışı üzerinde de çalışabilir - açıcı, açılırken arama tablosunun kendi kopyasını tutar, dolayısıyla arama tablosu sıkıştırılmakta olan verinin türünü ayarlar.


Fakat tahminci normal İngilizce cümle ile nasıl davranır? Verilen örnek çok güçlü bir fazlalığa sahiptir ve kazanç minimumdur.
Danubian Sailor

256 * 256 arama tablosu "bellek ile inanılmaz derecede tutumlu" görünmüyor ...!
MikeW

@MikeW 65 kilobayt.
redcalx

@redcalx 65 bayt olsaydı kabul edebilirdim!
MikeW

11

Önceden belirlenmiş bir sözlüğü destekleyen herhangi bir algoritma / kitaplık, örneğin zlib .

Bu şekilde, girişte görünmesi muhtemel olanla aynı türden bir metinle kompresörü hazırlayabilirsiniz. Dosyalar bir şekilde benzer ise (örneğin, tüm URL'ler, tüm C programları, tüm StackOverflow gönderileri, tüm ASCII-art çizimleri), giriş dosyalarının çoğunda veya tamamında belirli alt dizeler görünecektir.

Aynı alt dize bir girdi dosyasında birden çok kez tekrarlanırsa her sıkıştırma algoritması yerden tasarruf sağlar (örneğin, İngilizce metinde "the" veya C kodunda "int").

Ancak URL'ler söz konusu olduğunda belirli dizeler (ör. " Http: // www .", ".Com", ".html", ".aspx" genellikle her girdi dosyasında bir kez görünür. Bu nedenle, bunları dosyalar arasında paylaşmanız gerekir. her nasılsa dosya başına bir sıkıştırılmış oluşumdan ziyade, bunları önceden belirlenmiş bir sözlüğe yerleştirmek bunu başaracaktır.


2
Özel sözlüğün kullanımına ilişkin ipuçları: stackoverflow.com/questions/2011653
Trenton


4

Metni sadece kısaltmaktan değil, sıkıştırmaktan bahsediyorsanız, Deflate / gzip (gzip etrafında sarmalayıcı), zip daha küçük dosyalar ve metinler için iyi çalışır. Diğer algoritmalar, bzip2 gibi daha büyük dosyalar için oldukça etkilidir.

Wikipedia'da bir sıkıştırma süreleri listesi vardır. (verimlilik karşılaştırmasına bakın)

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
Dosyaları değil, metni sıkıştırmak istiyor.
Gumbo

3
Metni ve ikili dosyaları bu algoritmalarla sıkıştırabilirsiniz. Aslında, python ile çalışan bir cms sistemi içinde deflate kullanıyoruz.
Ryan Christensen

C # içinde dizeler için gzip kullanan bir örnek burada: csharphelp.com/archives4/archive689.html
Ryan Christensen

dizeleri sıkıştırmak için python'da
Ryan Christensen

3
gzip (ve zlib) deflate kullanır ve sarmalayıcı / çerçeveleme ek yükünü ekler. direct deflate / LZ77 (sözlük ek yükü ve verimlilik hala bu tür ve ayarların uygulanmasına bağlıdır) başa baş yükü azaltabilir. Bu, düzinelerce ila yüzlerce karakterden oluşan "kısa" dizeler içindir, elbette (veriyi büyütmekten kaçınmak için "bu sıkıştırılmış mıydı"? Metin arttıkça daha büyük ek yük önemli değildir. OP 50-1000 charter talep ederken, burada yayınlanan sayılar büyük metin dosyaları için görünmektedir (çalıştırmak için birçok saniye!) - buna kıyasla çok küçük .
user2864740

2

Unicode için Standart Sıkıştırma Şemasına bir göz atmak isteyebilirsiniz .

SQL Server 2008 R2 bunu dahili olarak kullanır ve% 50'ye kadar sıkıştırma sağlayabilir.


SCSU, İngilizce olmayan Unicode'u UTF-16 / MB kodlamalarında 'sıkıştırır'. İngilizce tabanlı Unicode / düz-eski-ASCII ise, UTF-8 ayrıca UTF-16'nın% 50'sini 'sıkıştırır' ..
user2864740
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.