1. 程式人生 > 實用技巧 >[LeetCode] 647. Palindromic Substrings(迴文子串)

[LeetCode] 647. Palindromic Substrings(迴文子串)

Description

Given a string, your task is to count how many palindromic substrings in this string.
給一個字串,你的任務是統計其中有多少迴文子串。

The substrings with different start indices or end indices are counted as different substrings even they consist of same characters.
起始索引和終止索引有一個不同即視為不同的迴文子串,哪怕它們由相同的字元構成。

Examples

Example 1

Input: "abc"
Output: 3
Explanation: Three palindromic strings: "a", "b", "c".

Example 2

Input: "aaa"
Output: 6
Explanation: Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa".

Note

  1. The input string length won't exceed 1000.
    輸入字串的長度不會超過 1000。

Hints

  1. How can we reuse a previously computed palindrome to compute a larger palindrome?
    如何使用之前的迴文子串結果生成新的迴文子串?

  2. If "aba" is a palidrome, is "xabax" a palindrome? Similarly is "xabay" a palidrome?
    如果 "aba" 是迴文,那麼 "xabax" 迴文嗎?類似地,"xabay" 迴文嗎?

  3. Complexity based hint:

    If we use brute-force and check whether for every start and end position a substring is a palindrome we have O(n^2) start-end pairs and O(n) palindromic check. Can we reduce the time for palindromic checks to O(1) by reusing some previous computation?
    如果我們暴力列舉並檢查每一個子串是否迴文,我們需要檢查 \(O(N^2)\)

    的 start-end 對和 \(O(N)\) 的迴文檢查。我們是否能通過利用之前的計算,將回文檢查的時間減少到 \(O(1)\)

Solution

暴力解法:從字串的每個元素開始,從中間向外擴張尋找回文,實際跑下來時間竟然還行,程式碼如下:

class Solution {
    private var count = 0

    fun countSubstrings(s: String): Int {
        for (i in s.indices) {
            expand(s, i, i)
            expand(s, i, i + 1)
        }

        return count
    }

    private fun expand(s: String, left: Int, right: Int) {
        var mLeft = left
        var mRight = right

        while (mLeft >= 0 && mRight <= s.lastIndex && s[mLeft] == s[mRight]) {
            count++
            mLeft--
            mRight++
        }
    }
}