จับคู่สองสาย แต่อนุญาตให้มีข้อผิดพลาดในระดับหนึ่ง


10

ฉันจะจับคู่สองสายได้อย่างไร แต่ในขณะเดียวกันก็อนุญาตให้จำนวนอักขระ X ไม่ถูกต้องในการแข่งขัน จำนวนข้อผิดพลาดควรเป็นตัวแปรที่ควบคุมได้

ในขณะที่จำนวนอักขระ X ไม่สามารถจับคู่ในสตริงได้ควรมีข้อ จำกัด เกี่ยวกับจำนวนการรันในลำดับ รับสองสายฉันอาจอนุญาตให้ 5 ตัวอักษรจะแตกต่างกัน แต่ไม่เกิน 2 ในแถว

ฉันกำลังมองหาอัลกอริทึมที่แนะนำสำหรับการเปรียบเทียบทั้งสองสายหรืออาจจะมีวิธีการแก้ปัญหาที่รู้จักกันแล้วสำหรับเรื่องนี้


4
Levenshtein ระยะทางอาจจะมีบางสิ่งบางอย่างที่จะมอง แต่เฉพาะของ 'ไม่เกิน 2 ในแถว' ไม่ได้เป็นส่วนหนึ่งของขั้นตอนวิธีการว่า ดูเพิ่มเติมหน้ามีจำนวนมากของขั้นตอนวิธีอื่น ๆ ที่เกี่ยวข้องที่อาจจะมีสิ่งที่คุณกำลังมองหา

@MichaelT ถ้าฉันมีบางอย่างเช่นนี้มันจะเหมาะกับความต้องการของฉันแน่นอน ขอบคุณ
เปิดใช้งานอีกครั้ง

@MichaelT ฉันพบสิ่งนี้> dotnetperls.com/levenshteinคุณควรใส่คำตอบนี้เพราะนี่เป็นสาเหตุที่แก้ไขปัญหาของฉันได้
เปิดใช้งานอีกครั้ง

คุณอาจต้องการดูการจับคู่ Soundex en.wikipedia.org/wiki/Soundex
Gilbert Le Blanc

คำตอบ:


12

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

ตัวอย่างของสิ่งนี้คือkitten-> sittingซึ่งมีระยะการแก้ไขสาม

  1. k itten -> s itten (แทน 's' สำหรับ 'k')
  2. sitt e n -> sitt i n (แทน 'i' สำหรับ 'e')
  3. sittin -> sittin g (เพิ่ม 'g' ตอนท้าย)

มีการแปรผันของอัลกอริธึมนี้โดยเฉพาะระยะทาง Damerau – Levenshteinซึ่งอนุญาตให้ขนย้ายตัวละครสองตัวที่อยู่ติดกัน ('hte' ถึง 'the' มีระยะ DL 1 และระยะทาง Levenshtein 2) และมักจะเหมาะสมกว่าสำหรับ ตรวจสอบการสะกด มีรูปแบบอื่น ๆ สำหรับแอปพลิเคชันที่ช่องว่างสำคัญ (สาย DNA)

ระยะทางของ Levenshtein นั้นเป็นที่รู้จักกันดีและไม่ยากเกินไปที่จะหา (ฉันเคยทำให้เกิดการใช้งานมันเป็นฟังก์ชั่นใน oracle - มันเร็วกว่าการดึงข้อมูลทั้งหมดแล้วเรียกใช้โค้ดคิวรี) Rosettacode มีจำนวนมาก (54) ของการดำเนินการของระยะทาง Levenshtein (โปรดทราบว่าบางภาษามีสิ่งนี้เป็นส่วนหนึ่งของห้องสมุดสตริงที่ไหนสักแห่ง - ถ้าคุณกำลังทำ Java ดูที่apache คอมมอนส์ lang ) Wikibooksมีการใช้งาน 31 แบบและคร่าวๆอย่างคร่าวๆที่ทั้งสองไม่แสดงรหัสเดียวกันสำหรับภาษาเดียวกัน

วิธีการทำงานของมันคือการสร้างเมทริกซ์ที่สอดคล้องกับความสัมพันธ์ระหว่างสองสตริง:

 .kitten
.0123456
s1123456
i2212345
t3321234
t4432123
i5543223
n6654332
g7765443

.แถวและคอลัมน์รับรองว่าคุณจะได้รับสตริงเป้าหมายโดย 'เพียง' การใส่ตัวอักษรแต่ละตัวจากสตริงที่ว่างเปล่า นี่ไม่ใช่กรณีในอุดมคติ แต่มีไว้เพื่อหว่านอัลกอริทึม

หากค่าเป็นจุดเดียวกัน ('i' == 'i') ค่าจะเหมือนกับค่าตามแนวทแยงมุมทางด้านซ้าย หากจุดสองจุดนั้นแตกต่างกัน ('s'! = 'k') ค่าจะน้อยที่สุด:

  • เส้นทแยงมุมขึ้นและไปทางซ้าย + 1 (การเปลี่ยนตัว)
  • เหนือ + 1 โดยตรง (การแทรก)
  • โดยตรงไปทางซ้าย + 1 (การลบ)

ค่าส่งคืนระยะทางแก้ไขคือค่าที่ด้านล่างขวาของเมทริกซ์

หากคุณติดตามจากขวาล่างถึงซ้ายบนโดยมีค่าต่ำสุดคุณจะเห็นการแก้ไขที่ทำไปแล้ว:

 .kitten
.0.   .
s.1   .
i  1  .
t   1 .
t    1.
i.....2
n      2
g......3

โปรดทราบว่านี่เป็นวิธีที่ค่อนข้างใช้หน่วยความจำมาก มันสามารถลดลงในขอบเขตหน่วยความจำโดยไม่สร้างเมทริกซ์แบบเต็ม - อัลกอริธึมทั้งหมดที่ใส่ใจคือชุดย่อยของข้อมูลและสามารถลดลงจากN*Mพื้นที่หนึ่งไปยังอีกที่หนึ่งได้2*max(N,M)โดยเพียงแค่เก็บแถวก่อนหน้า (และสิ่งที่คำนวณในปัจจุบัน) แถว). รหัสโครงการแสดงวิธีการนี้สามารถทำได้ (ด้วยรหัส C # เพื่อดาวน์โหลด)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.