5. Longest Palindromic Substring(C++)


とりあえず総当たりで

最初、効率的な方法が思いつかなかったので、とりあえず全てのsubstrのパターンをチェックする方法(O(n^2))です。

class Solution {
public:
    string longestPalindrome(string s) {
        std::string longest;
        const size_t size = s.size();
        for (size_t begin_pos = 0; begin_pos < size; begin_pos++) {
            for (size_t length = 1; begin_pos + length <= size; length++) {
                const std::string sub_str = s.substr(begin_pos, length);
                if (isPalindromic(sub_str) && longest.size() < sub_str.size()) {
                    longest = sub_str;
                }
            }
        }
        return longest;
    }

private:
    static bool isPalindromic(const std::string& src) {
        std::string reversal = src;
        std::reverse(reversal.begin(), reversal.end());
        return src == reversal;
    }
};

もちろんコストが掛かるので、LeetCodeが許してくれるはずがありません。
タイムアウトになります。

両サイドの文字をチェックする方法

Discussionを見て参考にし、両サイドの文字が一致するかを見ていく方法で実装してみました。

class Solution {
public:
    string longestPalindrome(string s) {
        std::string longest = s.substr(0, 1); // ①
        const size_t size = s.size();
        for (size_t i = 0; i < size; i++) {
            // ②
            // ex) "aba"
            for (size_t width = 1; 0 <= static_cast<int>(i-width) && i+width < size; width++) {
                if (s[i-width] != s[i+width]) {
                    break;
                }
                const size_t length = width*2 + 1;
                if (longest.size() < length) {
                    longest = s.substr(i-width, length);
                }
            }
            // ③
            // ex) "abba"
            for (size_t width = 1; 0 <= static_cast<int>(i+1-width) && i+width < size; width++) {
                if (s[i+1-width] != s[i+width]) {
                    break;
                }
                const size_t length = width*2;
                if (longest.size() < length) {
                    longest = s.substr(i+1-width, length);
                }
            }
        }
        return longest;
    }
};

ざっと説明すると、

  1. “abc” が渡された際は任意の文字を返さないといけないのと、②と③では条件に一致しないため、先頭の文字で初期化する
  2. 奇数のsubstrを想定し、真ん中の文字から同じ距離離れた文字が一致するかを見ていく
  3. 偶数のsubstrを想定し、同じ距離離れた文字を比較していく

これで計算量は最短で線形時間(O(N))になりました。

ちなみに、unsigned 型同士(size_t)で計算すると結果も unsigned で出てくるので、for 分の条件については明示的にキャストが必要です。
-1 で抜けてほしいところが、キャストしないと unsigned int max と比較されてしまうので、条件がtrueとなり、string要素への不正アクセスが発生します。

以上です!

,

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です