อัลกอริทึมการบีบอัดที่มีประสิทธิภาพสำหรับสตริงข้อความสั้น [ปิด]


126

ฉันกำลังค้นหาอัลกอริทึมเพื่อบีบอัดสตริงข้อความขนาดเล็ก: 50-1000 ไบต์ (เช่น URL) อัลกอริทึมใดทำงานได้ดีที่สุดสำหรับสิ่งนี้


1
คุณต้องการใช้สตริงที่บีบอัดเหล่านี้ที่ไหน
Gumbo

1
สิ่งนี้เกิดขึ้นtinyurlsหรือเกี่ยวข้องกับพื้นที่จัดเก็บข้อมูลหรือไม่?
nik

6
ฉันสนใจอัลกอริทึมสำหรับการบีบอัด URL อัตราส่วนการบีบอัดที่ดีที่สุดมีความสำคัญมากกว่าแล้วก็คุ้มค่า ไม่สนใจบริการออนไลน์เช่น tinyurls หรือ tr.im. ฉันกำลังมองหาอัลกอริทึมไม่ใช่บริการ อย่าคิดว่าข้อมูลอื่นจะเป็นประโยชน์ ...
Vasily Korolev

3
@Gumbo: "อัลกอริธึมการบีบอัดข้อความสำหรับสตริงสั้น" ก็เพียงพอแล้วสำหรับการค้นหาอัลกอสทำไมคุณถึงสนใจที่จะรู้ว่ามันมีไว้เพื่ออะไร ฉันแน่ใจว่า OP จะสามารถหาคนที่ทำในสิ่งที่เขาต้องการได้
Dervin Thunk

7
@ คำใบ้เล็ก ๆ น้อย ๆ : เมื่อใดก็ตามที่คุณถามคำถามเกี่ยวกับ SO ในรูปแบบ " XYZ ที่ดีที่สุดคืออะไร" คำถามของคุณเกือบจะได้รับการโหวตให้ปิดเพราะการขอสิ่งที่ดีที่สุดอาจนำไปสู่ผลิตภัณฑ์ที่ไม่จำเป็น การเปรียบเทียบหรือในกรณีที่เลวร้ายที่สุดแม้แต่สงครามเปลวไฟ (โดยปกติจะใช้เวลาเปลี่ยนแปลงเพียงเล็กน้อยเพื่อหลีกเลี่ยงสิ่งนั้น: หากคุณถามคำถามเดียวกันเช่น "โปรดแนะนำ XYZ" คุณจะไม่ได้รับการปิดโหวตมากนักแม้ว่าโดยพื้นฐานแล้วจะเป็นคำถามเดียวกัน
ก็ตาม

คำตอบ:


62

ตรวจสอบSmaz :

Smaz เป็นไลบรารีการบีบอัดแบบง่ายที่เหมาะสำหรับการบีบอัดสตริงที่สั้นมาก


17
ดูgithub.com/antirez/smaz/blob/master/smaz.c - นี่คือรูปแบบของการเข้ารหัสไม่ใช่การบีบอัดต่อ se (อย่างน้อยก็ไม่ใช่ทั้งหมด) เขาใช้พจนานุกรมคำและตัวอักษรแบบคงที่
Roy Tinker

7
หมายเหตุ: นี่เป็นโครงการของ antirez เขาเป็นหนึ่งในผู้เขียนหลักของ Redis และมีชื่อเสียงอย่างมากในการเผยแพร่รหัสการผลิตคุณภาพสูง
Homer6

7
อัลกอริทึม smaz ได้รับการปรับให้เหมาะกับข้อความภาษาอังกฤษดังนั้นจึงไม่สามารถใช้งานได้ดีกับสตริงแบบสุ่ม นี่คือบางส่วนตัวอย่าง (มี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
ลองดูที่การบีบอัดที่ต่ำกว่า แต่อัลกอริทึมที่รวดเร็ว shoco ed-von-schleck.github.io/shoco
Dickey Singh

เพิ่ม Unishox ห้องสมุดของฉันไปที่รายการgithub.com/siara-cc/unishox ทำงานได้ดีกว่า Smaz และ Shoco และรองรับการบีบอัดสตริง UTF-8
อรุณ

28

Huffman มีต้นทุนคงที่คือตาราง Huffman ดังนั้นฉันไม่เห็นด้วยเป็นทางเลือกที่ดี

มีเวอร์ชันที่ปรับเปลี่ยนได้ซึ่งช่วยลดปัญหานี้ได้ แต่อัตราการบีบอัดอาจได้รับผลกระทบ จริงๆแล้วคำถามที่คุณควรถามคือ "อัลกอริทึมใดในการบีบอัดสตริงข้อความที่มีลักษณะเหล่านี้" ตัวอย่างเช่นหากคาดว่าจะมีการทำซ้ำเป็นเวลานานการเข้ารหัส Run-Lengh แบบธรรมดาอาจเพียงพอ หากคุณสามารถรับประกันได้ว่าจะมีเฉพาะคำภาษาอังกฤษช่องว่างเครื่องหมายวรรคตอนและตัวเลขเป็นครั้งคราว Huffman ที่มีตาราง Huffman ที่กำหนดไว้ล่วงหน้าอาจให้ผลลัพธ์ที่ดี

โดยทั่วไปอัลกอริทึมของตระกูล Lempel-Ziv มีการบีบอัดและประสิทธิภาพที่ดีมากและมีไลบรารีสำหรับพวกเขามากมาย ฉันจะไปด้วย

ด้วยข้อมูลที่ว่าสิ่งที่ถูกบีบอัดเป็น URL ฉันขอแนะนำว่าก่อนที่จะบีบอัด (ด้วยอัลกอริทึมใดก็ตามที่สามารถใช้ได้อย่างง่ายดาย) คุณ CODIFY พวกเขา URL เป็นไปตามรูปแบบที่กำหนดไว้อย่างดีและบางส่วนสามารถคาดเดาได้สูง การใช้ประโยชน์จากความรู้นี้คุณสามารถเข้ารหัส URL ให้เป็นสิ่งที่เล็กลงเพื่อเริ่มต้นและแนวคิดเบื้องหลังการเข้ารหัส Huffman สามารถช่วยคุณได้ที่นี่

ตัวอย่างเช่นการแปล URL เป็นบิตสตรีมคุณสามารถแทนที่ "http" ด้วยบิต 1 และอย่างอื่นด้วยบิต "0" ตามด้วยโปรโคทอลจริง (หรือใช้ตารางเพื่อรับโปรโตคอลทั่วไปอื่น ๆ เช่น https ftp, ไฟล์) ": //" สามารถทิ้งได้ทั้งหมดตราบเท่าที่คุณสามารถทำเครื่องหมายจุดสิ้นสุดของโปรโตคอลได้ เป็นต้นไปอ่านเกี่ยวกับรูปแบบ URL และคิดว่าจะสามารถเข้ารหัสได้อย่างไรเพื่อให้ใช้พื้นที่น้อยลง


4
ไม่ใช่ว่าตาราง huffman จะเหมือนกันสำหรับไฟล์ทั้งหมดซึ่งจะสมเหตุสมผลถ้าไฟล์ทั้งหมดคล้ายกัน
finnw

1
หากคุณมีไฟล์ขนาดเล็กที่คล้ายกันจำนวนมากแสดงว่าคุณทำผิดทั้งหมด ขั้นแรกให้รวมเข้าด้วยกันทั้งหมด (เช่นเดียวกับน้ำมันดิน) แล้วบีบอัดสิ่งนั้น คุณจะได้รับการบีบอัดที่ดีขึ้นและปัญหาจะสิ้นสุดที่ "50-1000 ไบต์"
Daniel C. Sobral

8
@ แดเนียล: ขึ้นอยู่กับว่าคุณต้องการเข้าถึงข้อมูลบีบอัดแบบสุ่มหรือไม่ การบีบอัดทั้งหมดเข้าด้วยกันจะป้องกันไม่ให้ระบบบีบอัดส่วนใหญ่
Steve Jessop

22

ฉันไม่มีรหัสในมือ แต่ฉันชอบวิธีการสร้างตารางการค้นหา 2D ขนาด 256 * 256 ตัวอักษร ( RFC 1978 , PPP Predictor Compression Protocol ) ในการบีบอัดสตริงที่คุณวนซ้ำในแต่ละอักขระและใช้ตารางการค้นหาเพื่อรับ 'ทำนาย' อักขระถัดไปโดยใช้อักขระปัจจุบันและก่อนหน้าเป็นดัชนีในตาราง หากมีรายการที่ตรงกันให้คุณเขียน 1 บิตเดียวมิฉะนั้นให้เขียน 0 อักขระและอัปเดตตารางการค้นหาด้วยอักขระปัจจุบัน วิธีนี้โดยพื้นฐานแล้วจะรักษาตารางการค้นหาแบบไดนามิก (และหยาบ) ของอักขระถัดไปที่น่าจะเป็นไปได้มากที่สุดในสตรีมข้อมูล

คุณสามารถเริ่มต้นด้วยตารางการค้นหาที่เป็นศูนย์ แต่จะใช้งานได้ดีที่สุดในสตริงที่สั้นมากหากเริ่มต้นด้วยอักขระที่เป็นไปได้มากที่สุดสำหรับคู่อักขระแต่ละคู่ตัวอย่างเช่นสำหรับภาษาอังกฤษ ตราบใดที่ตารางการค้นหาเริ่มต้นเหมือนกันสำหรับการบีบอัดและการคลายการบีบอัดคุณไม่จำเป็นต้องปล่อยมันลงในข้อมูลที่บีบอัด

อัลกอริทึมนี้ไม่ได้ให้อัตราส่วนการบีบอัดที่ยอดเยี่ยม แต่ประหยัดอย่างไม่น่าเชื่อด้วยทรัพยากรหน่วยความจำและ CPU และยังสามารถทำงานกับสตรีมข้อมูลอย่างต่อเนื่อง - ตัวคลายการบีบอัดจะรักษาสำเนาของตารางการค้นหาของตัวเองในขณะที่คลายการบีบอัดดังนั้นตารางการค้นหา ปรับตามประเภทของข้อมูลที่กำลังบีบอัด


แต่ตัวทำนายจะทำตัวอย่างไรกับประโยคภาษาอังกฤษปกติ? ตัวอย่างที่ระบุมีความซ้ำซ้อนที่แข็งแกร่งมากและอัตราขยายจะน้อยที่สุด
Danubian Sailor

ตารางการค้นหา 256 * 256 ไม่ได้ "ประหยัดอย่างไม่น่าเชื่อกับหน่วยความจำ" ... !
MikeW

@MikeW ก็ 65 กิโลไบต์
redcalx

@redcalx ถ้ามันเป็น 65 ไบต์ฉันอาจจะเห็นด้วย!
MikeW

11

ขั้นตอนวิธีการใด ๆ / ห้องสมุดที่สนับสนุนที่ตั้งไว้ในพจนานุกรมเช่นzlib

ด้วยวิธีนี้คุณสามารถไพรม์คอมเพรสเซอร์ด้วยข้อความประเภทเดียวกับที่น่าจะปรากฏในอินพุต หากไฟล์มีความคล้ายคลึงกันในทางใดทางหนึ่ง (เช่น URL ทั้งหมดโปรแกรม C ทั้งหมดโพสต์ StackOverflow ทั้งหมดภาพวาด ASCII ทั้งหมด) สตริงย่อยบางอย่างจะปรากฏในไฟล์อินพุตส่วนใหญ่หรือทั้งหมด

ทุกอัลกอริธึมการบีบอัดจะช่วยประหยัดเนื้อที่หากสตริงย่อยเดียวกันซ้ำหลายครั้งในไฟล์อินพุตเดียว (เช่น "the" ในข้อความภาษาอังกฤษหรือ "int" ในรหัส C)

แต่ในกรณีของ URL บางสตริง (เช่น " http: // www .", ".com", ".html", ".aspx" จะปรากฏหนึ่งครั้งในไฟล์อินพุตแต่ละไฟล์ดังนั้นคุณต้องแชร์ระหว่างไฟล์ต่างๆ แทนที่จะมีหนึ่งเหตุการณ์ที่บีบอัดต่อไฟล์การวางไว้ในพจนานุกรมที่ตั้งไว้ล่วงหน้าจะทำให้ได้สิ่งนี้


2
เคล็ดลับในการใช้พจนานุกรมที่กำหนดเอง: stackoverflow.com/questions/2011653
Trenton

4

โดยทั่วไปการเข้ารหัส Huffman ใช้งานได้ดีสำหรับสิ่งนี้


4
นี่ไม่ใช่คำตอบแบบลิงก์เท่านั้น หากไม่มีลิงก์ก็ยังคงเป็นคำตอบที่ถูกต้อง
SL Barth - คืนสถานะ Monica

.. และยังไม่ใช่คำตอบที่ดี (นำข้อมูลที่เกี่ยวข้องมาไม่เพียงพอ)
user2864740

4

หากคุณกำลังพูดถึงการบีบอัดข้อความไม่ใช่แค่การย่อให้สั้นแล้ว Deflate / gzip (wrapper รอบ gzip) zip จะทำงานได้ดีสำหรับไฟล์และข้อความขนาดเล็ก อัลกอริทึมอื่น ๆ มีประสิทธิภาพสูงสำหรับไฟล์ขนาดใหญ่เช่น bzip2 เป็นต้น

วิกิพีเดียมีรายการเวลาบีบอัด (มองหาการเปรียบเทียบประสิทธิภาพ)

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
เขาต้องการบีบอัดข้อความไม่ใช่ไฟล์
Gumbo

3
คุณสามารถบีบอัดข้อความและไบนารีด้วยอัลกอริทึมเหล่านี้ ในความเป็นจริงเราใช้ deflate ภายในระบบ cms ที่ทำงานใน python
Ryan Christensen

ตัวอย่างใน C # ที่ใช้ gzip สำหรับสตริงอยู่ที่นี่: csharphelp.com/archives4/archive689.html
Ryan Christensen

โมดูล zlib ใน python สำหรับการบีบอัดสตริง: python.org/doc/2.5.2/lib/module-zlib.html
Ryan Christensen

3
gzip (และ zlib) ใช้ deflate และเพิ่ม wrapper / framing overhead .. direct deflate / LZ77 (ค่าใช้จ่ายในพจนานุกรมและประสิทธิภาพยังคงขึ้นอยู่กับการใช้งานและการตั้งค่าดังกล่าว) สามารถลดค่าใช้จ่ายที่คุ้มทุนได้ แน่นอนว่าสำหรับสตริง "สั้น" ที่มีอักขระตั้งแต่หลายสิบถึงหลายร้อยตัว (ยังควรมีการระบุว่า "ถูกบีบอัด" หรือไม่เพื่อหลีกเลี่ยงการขยายข้อมูล) ค่าใช้จ่ายพิเศษที่ใหญ่ขึ้นไม่สำคัญ .. เมื่อข้อความเพิ่มขึ้น ตัวเลขที่โพสต์ที่นี่ดูเหมือนจะเป็นสำหรับไฟล์ข้อความขนาดใหญ่ (ใช้เวลาหลายวินาที!) ในขณะที่ OP ขอ 50-1000 ตัวอักษร - น้อยมากเมื่อเปรียบเทียบ
user2864740

2

คุณอาจต้องการที่จะดูที่โครงการการบีบอัดมาตรฐาน Unicode

SQL Server 2008 R2 ใช้ภายในและสามารถบีบอัดได้ถึง 50%


SCSU 'บีบอัด' Unicode ที่ไม่ใช่ภาษาอังกฤษในการเข้ารหัส UTF-16 / MB ถ้า Unicode ที่ใช้ภาษาอังกฤษ / plain-old-ASCII UTF-8 จะ 'บีบอัด' 50% ของ UTF-16 ด้วย ..
user2864740
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.