最長の回文サブストリング(Javaバージョン)

ディレクトリ

1、タイトル

2、例

3、ソリューション

3.0ブルートフォース

3.1動的なプログラミング

3.2センターの拡張アルゴリズム

3.3 Manacherアルゴリズム

4.リファレンス


1、タイトル

文字列を与えられた  s見つけるために、  s 最も長いサブストリングパリンドロームを。あなたは、と仮定することができる  s 1000年の最大の長さ。

2、例

示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。

示例 2:
输入: "cbbd"
输出: "bb"

3、ソリューション

3.0ブルートフォース

最長の回文文字列を保存し、文字列が回文であるかどうかを判断するために、解決するために暴力、リストのすべてのサブ文字列:これは、他の解決策がない場合、あなたが考える必要がありますする必要があります。

    public static String longestPalindrome(String s) {
        String ans = "";
        int max = 0;
        int len = s.length();
        for (int i = 0; i < len; i++) {
            for (int j = i + 1; j <= len; j++) {
                String tmp = s.substring(i, j);
                if (isPalindromic(tmp) && tmp.length() > max) {
                    ans = tmp;
                    max = j - i;
                }
            }
        }
        return ans;
    }

    private static boolean isPalindromic(String s) {
        int len = s.length();
        for (int i = 0; i < len / 2; i++) {
            if (s.charAt(i) != s.charAt(len - i - 1)) {
                return false;
            }
        }
        return true;
    }

時間計算:時間複雑度はO(n³)であるように、パリンドロームO(n)の内部ループか否かを判定するためのOへのループの2つ(n²)。

宇宙複雑:O(1)、定数変数。

3.1動的なプログラミング

暴力的な解決時間の複雑さが高すぎる、我々は重複した裁判官を削除するには、いくつかの暴力的な解決策を考えることができます。

最初の定義:文字列s文字列添字jをP(i、j)の添え字iをし、インデックスi Sから文字列へのインデックスjがP(i、j)は、次いで、パリンドローム配列である場合=真、それ以外の場合はP(i、j)は=偽。下図のように:

则P(i、j)は=(P(I + 1、J - 1)&& S [I] == S [J])。

我々は(i、j)はパリンドロームの文字列を決定するための関数を呼び出す必要はありませんPの場合を知りたいのであれば、唯一の(I + 1、J-1)Pは非常に短い時間の複雑さという、ケースであることを知ってする必要がありますO(N)。したがって、我々は時間の動的プログラミング、空間の方法を使用することができ、我々はP(i、j)が格納さを得ました。

image.png

もしS [I + 1、J-1]は限りS [i]を== S [j]は、我々が決定することができ、S [I、j]がパリンドローム配列であるとして、回文配列です。

注意:

シーク長さは、Pを求めるなどのI>ここでj、[1]における式Pに経験我々[I] [J]と、1と処方しない上辺の長さときP(i、j)は2であります[2]、我々は、P [1 + 1] [2-1] = P [2] [1]を知っておく必要があり、及びP [2] [1]、S [2、1]はパリンドローム配列ではない表します私たちは一人で判断する必要があるので、これは、明らかに間違っています。

したがって、我々は最初のように式を用いて、P [I、J]のパリンドローム配列の長さを初期化する上部提案P(i、j)は=(P(I + 1、J-1)&& S [I] == Sは、[J])は、すべての上の文字のそれぞれ外側に拡張、3、5の長さ、およびすべての奇数長の両側を探し出します。同様に、偶数長さ6の式を使用して2 P [I、I + 1]初期パリンドローム配列の長さは、4の長さは、全てが全て探し出しなります。

    public static String longestPalindrome(String s) {
        int sLen = s.length();
        int maxLen = 0;
        String ans = "";
        boolean[][] P = new boolean[sLen][sLen];
        // 遍历所有长度
        for (int len = 1; len <= sLen; len++) {
            for (int start = 0; start < sLen; start++) {
                int end = start + len - 1;
                // 下标越界,结束循环
                if (end >=sLen) {
                    break;
                }
                P[start][end] = (len == 1 || len == 2 || P[start + 1][end - 1]) && s.charAt(start) == s.charAt(end);
                if (P[start][end] && len > maxLen) {
                    maxLen = len;
                    ans = s.substring(start, end + 1);
                }
            }
        }
        return ans;
    }

時間の複雑さ:2サイクルO(n²)。

空間複雑:各サブストリングPPケースO(n²)を有する2次元アレイを節約。

例えば「babad」)にスペース使用:(以下の分析

我々は、サブストリングのケース5の長さを見つけたとき、実際にのみケース4の長さ、及び1及び2の長さと、実際には、もはや必要ストリング3を使用します。

しかし、我々は添字P配列で行われていないサイクルのために、シンクタンクを最適化する方法はありません。

私たちはアイデアを、同じ式の種類を変更するよう:

実際には、我々は最初に、我々は唯一のライン上に後方横断する必要があるので、私+1は、私を知っている知っている、漸化式から見ることができます。

    public static String longestPalindrome(String s) {
        int sLen = s.length();
        String ans = "";
        boolean[][] P = new boolean[sLen][sLen];

        for (int i = sLen - 1; i >= 0; i--) {
            for (int j = i; j < sLen; j++) {
                P[i][j] = (s.charAt(i) == s.charAt(j)) && (j - i < 2 || P[i + 1][j - 1]);
                if (P[i][j] && j - i + 1 > ans.length()) {
                    ans = s.substring(i, j + 1);
                }
            }
        }
        return ans;
    }

時間の複雑さと空間の複雑さを変更していないと前に、私たちは宇宙の複雑さの最適化を見ることができます。

i行目では、我々は唯一のI + 1行の情報を必要なときに求め、そのためJ以前のように、J J-1の情報を必要に応じても、逆にする必要がある場合。

    public static String longestPalindrome(String s) {
        int sLen = s.length();
        String ans = "";
        boolean[] P = new boolean[sLen];

        for (int i = sLen - 1; i >= 0; i--) {
            for (int j = sLen - 1; j >= i; j--) {
                P[j] = s.charAt(i) == s.charAt(j) && (j - i < 2 || P[j - 1]);
                if (P[j] && j - i + 1 > ans.length()) {
                    ans = s.substring(i, j + 1);
                }
            }
        }

        return ans;
    }

時間計算:定数O(n²)。

宇宙複雑:O(n)とに縮小。

3.2センターの拡張アルゴリズム

私たちは、各サイクルの中心を選択することができるように我々は、特定のパリンドローム配列が対称であることを知って、程度の拡張のために、文字はおよそに等しいかどうかを判断します。

image.png

我々は、合計して、または拡張の先頭から2つの文字の間に、拡張文字から開始する必要がありますので、奇数と偶数列の文字列は、存在するので

N +(N-1)センター。

    public static String longestPalindrome(String s) {
        if (s == null || s.length() < 1) {
            return "";
        }
        int start = 0, end = 0;
        for (int i = 0; i < s.length(); i++) {
            int len1 = expandAroundCenter(s, i, i);
            int len2 = expandAroundCenter(s, i, i+1);

            int len = Math.max(len1, len2);
            if (len > end - start) {
                start = i - (len-1) / 2;
                end = i + len / 2;
            }
        }

        return s.substring(start, end + 1);
    }

    public static  int expandAroundCenter(String s, int left, int right) {
        int L = left, R = right;
        while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {
            L--;
            R++;
        }
        return (R-1) - (L+1) + 1;
    }

3.3 Manacherアルゴリズム

https://www.cnblogs.com/bitzhuwei/p/Longest-Palindromic-Substring-Part-II.html

4.リファレンス

https://leetcode-cn.com/problems/longest-palindromic-substring/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-bao-gu/

https://www.cnblogs.com/bitzhuwei/p/Longest-Palindromic-Substring-Part-II.html

公開された95元の記事 ウォン称賛16 ビュー50000 +

おすすめ

転載: blog.csdn.net/tiankong_12345/article/details/102018257