Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Python

โปรแกรมหาขอบพาลินโดรม (Palindromic Borders) ในสตริงใน Python

สมมติว่าเรามีสตริง str ขอบ (Border) ของสตริงคือ substring ที่เป็น proper prefix และ suffix พร้อมกัน เช่น 'ab' เป็น border ของ 'ababab' ขอบที่เป็นพาลินโดรม (Palindrome Border) คือขอบที่ตัวมันเองเป็นพาลินโดรม กำหนด f(str) = จำนวน palindrome borders ของ str ต้องหาผลรวม f(str_k) สำหรับทุก substring str_k ที่ไม่ว่าง modulo 10^9+7

ตัวอย่าง str = 'pqpqp' ผลลัพธ์ = 5 มี substring 15 ตัว แต่มี 4 ตัวที่มี palindromic borders: pqp (1), pqpqp (2), qpq (1), pqp (1) รวม = 5

ขั้นตอนการแก้ปัญหา

  • ใช้ Manacher-like Algorithm ขยาย palindrome จากศูนย์กลาง
  • แยกคำนวณสำหรับ palindrome ความยาวคี่ (odd) และคู่ (even)
  • ใช้ Dictionary นับความถี่ของแต่ละ palindrome substring
  • สำหรับแต่ละ palindrome ที่มีความถี่ f เพิ่ม f*(f-1)/2 เข้าคำตอบ
  • Modulo 1,000,000,007

ตัวอย่างโค้ด

def palindrome_calculator(input_dict):
    ans = 0
    for item1, item2 in input_dict.items():
        ans += item2 * (item2 - 1) // 2
    return ans

def str_check(string):
    t_str = string[0]
    for s in string:
        if s != t_str:
            return False
    return True

def string_res(string):
    ans = 0
    for i in range(2, len(string) + 1):
        ans += i * (i - 1) // 2
        ans %= 1000000007
    return ans

def solve(string):
    if str_check(string):
        return string_res(string)
    ans = 0
    odd_list = [[], {}, 1]
    for s in string:
        if s not in odd_list[1]:
            odd_list[1][s] = 0
        odd_list[1][s] += 1
    for i in range(len(string)):
        odd_list[0].append(i)
    ans += palindrome_calculator(odd_list[1])
    even_list = [[], {}, 1]
    for i in range(len(string) - 1):
        if string[i] == string[i + 1]:
            even_list[0].append(i)
            tmp = string[i:i + 2]
            if tmp not in even_list[1]:
                even_list[1][tmp] = 0
            even_list[1][tmp] += 1
    ans += palindrome_calculator(even_list[1])
    for val in range(3, len(string)):
        if val % 2 == 0:
            wt = even_list
        else:
            wt = odd_list
        new_t = [[], {}, val]
        for index in wt[0]:
            if index - 1 >= 0 and index + val - 2 < len(string) and string[index - 1] == string[index + val - 2]:
                new_t[0].append(index - 1)
                tmp = string[index - 1 : index - 1 + val]
                if tmp not in new_t[1]:
                    new_t[1][tmp] = 0
                new_t[1][tmp] += 1
        ans += palindrome_calculator(new_t[1])
        ans %= 1000000007
        if val % 2 == 0:
            even_list = new_t
        else:
            odd_list = new_t
    return ans

print(solve('pqpqp'))

อินพุต

'pqpqp'

เอาต์พุต

5