11. เชือก

-

11. 1. พาลินโดรม

พาลินโดรมคือคำหรือวลีที่สะกดเหมือนกันทุกประการเมื่ออ่านไปข้างหน้าหรือข้างหลัง พาลินโดรมได้รับอนุญาตให้เป็นตัวพิมพ์เล็กหรือตัวพิมพ์ใหญ่ โดยมีการเว้นวรรค เครื่องหมายวรรคตอน และตัวแบ่งคำ

อัลกอริทึมที่ตรวจสอบพาลินโดรมเป็นคำถามสัมภาษณ์การเขียนโปรแกรมทั่วไป

คำว่า racecar เป็นพาลินโดรมที่ถูกต้อง เนื่องจากเป็นคำที่สะกดเหมือนกันทั้งตอนพื้นหลังและข้างหน้า ตัวอย่างด้านล่างแสดงกรณีที่ถูกต้องของพาลินโดรม racecar

|     |
racecar -> r == r

 |   |
racecar -> a == a

  | |
racecar -> c == c

   |
racecar -> left index == right index -> return true

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

func isPalindrome(_ str: String) -> Bool {
    let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil)
    let length = strippedString.count
    
    if length > 1 {
        return palindrome(strippedString.lowercased(), left: 0, right: length - 1)
    }
    
    return false
}
private func palindrome(_ str: String, left: Int, right: Int) -> Bool {
    if left >= right {
        return true
    }
    
    let lhs = str[str.index(str.startIndex, offsetBy: left)]
    let rhs = str[str.index(str.startIndex, offsetBy: right)]
    
    if lhs != rhs {0
        return false
    }
    
    return palindrome(str, left: left + 1, right: right - 1)
}

11. 2. อัลกอริทึมของ Manacher

อัลกอริทึมของ Manacher เป็นอัลกอริทึมสำหรับการค้นหาพาลินโดรมในสตริง และความซับซ้อนของเวลาคือ O (n) (โดยที่ n คือความยาวของสตริง)

อัลกอริทึมใช้สตริง S เป็นอินพุตและส่งกลับ:

  • อาร์เรย์จำนวนเต็ม A ที่มีความยาวเท่ากับสตริง S และองค์ประกอบ A [i] ของแต่ละ A คือความยาวของรัศมีรัศมีที่ยาวที่สุดของสตริงที่ i (กล่าวคือ S[(i−A[i]) ⋯(i+A[i])] คือสตริงที่ขายแล้ว และ S[(i−A[i]−1)⋯(i+A[i]+1)] ไม่ใช่สตริงที่ขาย )

ตัวอย่างเช่น สำหรับอินพุต S = 'banana' ผลลัพธ์ของ A คือ:

อัลกอริทึมเป็นดังนี้:

  1. ฉันดำเนินการจาก 0 ถึง n-1 (n = | S |)
  2. R = สูงสุด (j + A [j]) สำหรับ j ทั้งหมดที่มี j ‹ i ให้ j เป็น p (R = พี + ​​A [พี])
  3. ค่าเริ่มต้นของ A [i] ถูกกำหนดขึ้นอยู่กับว่า i ≤ R หรือไม่
  • ถ้า i› R ค่าเริ่มต้นของ A [i] จะเป็นศูนย์
  • ถ้า i ≤ R แล้ว i จะเป็นดัมพ์การขายที่มีศูนย์กลางอยู่ที่ p ในเวลานี้ เราได้จุดสมมาตร i 'ของฉันรอบ p ค่าเริ่มต้นของ A [i] คือ min (R-i, A [i ‘])

4. จากค่าเริ่มต้นของ A [i] A [i] จะเพิ่มขึ้นจนกระทั่ง S [i-A [i]] และ S [i + A [i]] เท่ากัน จากนั้นถึง i

11. 3. ทรี

หมายถึงชุดลำดับของโครงสร้างข้อมูลต้นไม้ที่ใช้ในการจัดเก็บชุดไดนามิกหรืออาร์เรย์ที่เชื่อมโยงด้วยสตริง ไม่เหมือนกับแผนผังการค้นหาแบบไบนารี โหนดบนแผนผังจะไม่เก็บคีย์ที่เกี่ยวข้องกับโหนดนั้น ตำแหน่งบนแผนผังแสดงถึงคีย์ปัจจุบันแทน ผู้สืบทอดทุกโหนดของโหนดใดโหนดหนึ่งจะมีคำนำหน้าเหมือนกันกับโหนด และโหนดรูทจะมีสตริงว่าง ค่าไม่มีอยู่ในโหนดทั้งหมด แต่มีเฉพาะที่โหนดปลายสุดหรือโหนดด้านในที่สอดคล้องกับคีย์เฉพาะเท่านั้น เพื่อเพิ่มประสิทธิภาพการใช้พื้นที่ของทรีคำนำหน้า จึงมีจินตนาการถึงทรีคำนำหน้าขนาดกะทัดรัด คำว่า trie มาจากคำว่า reTRIEval Edward Fredkin ผู้สร้างคำนี้ ออกเสียงคำเดียวกับ 'tree' แต่คนอื่นๆ ออกเสียงว่า 'trai'

เหตุใดฉันจึงควรใช้ TRIE
เพื่อการค้นหาข้อมูลข้อความจำนวนมากอย่างรวดเร็วและมีประสิทธิภาพ
ดังนั้น Trie จึงเป็นโครงสร้างข้อมูลที่สามารถดึงพจนานุกรมหรือการเติมข้อความอัตโนมัติทางอินเทอร์เน็ตได้อย่างมีประสิทธิภาพ

ตามที่กล่าวไว้ก่อนหน้านี้ ชื่อ TRIE มาจาก TREE RETRIEVAL ลักษณะทั่วไปมากที่สุดคือข้อมูลคำหลักมีเพียงโหนดสุดท้าย โหนดที่เหลือไม่มีข้อมูลและมีเพียงลิงก์เท่านั้น

11. 4. ต้นไม้ต่อท้าย

Suffix tree เป็นโครงสร้างข้อมูลรูป trie ที่แสดงถึงส่วนต่อท้ายทั้งหมดของสตริง
trie เรียกว่า prefix tree ความแตกต่างระหว่างโครงสร้างข้อมูลคือเมื่อมีคำว่า Banana คำว่า Trie จะเก็บเฉพาะคำว่า Banana แต่ต้นไม้ต่อท้ายจะเป็นเช่น Banana, Anana, nana, ana, na, a จะบันทึกจำนวนกรณีทั้งหมดที่ได้มา มาจากคำว่ากล้วย เหตุผลในการจัดเก็บเคสทั้งหมดอย่างไร้ประโยชน์ก็เพราะคุณต้องค้นหาสตริง ในกรณีของโครงสร้างข้อมูล Trie คุณสามารถค้นหาคำว่า Banana แบบเต็มได้เป็นคำบางส่วน เช่น ban, ba แต่คุณไม่สามารถหาคำว่า nan, ana ได้ เพื่อแก้ปัญหานี้ ดูเหมือนว่าจะเป็นต้นไม้ต่อท้ายที่ช่วยปรับปรุงไตร

เนื่องจากขอบสามารถมีป้ายชื่อสตริงได้ จึงต้องสร้างความแตกต่างระหว่างสองความหมายของ 'ความลึก' ประการแรกคือความลึกของโหนด ความลึกของโหนดหมายถึงจำนวนขอบที่ต้องผ่านจากรูทไปยังโหนด ประการที่สองคือความลึกของฉลาก นี่คือความยาวรวมของป้ายกำกับขอบสำหรับขอบในเส้นทางจากรูทถึงโหนด