最长回文子串 (动态规划法、中心扩展算法)

问题描述:

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。

思考:

嗯,回文嘛!就是顺序读取和逆序读取的结果是一样的,那我们可以使用两个for循环来不断的截取给定的字符串S,然后判断截取后的字符串是不是回文串,与此同时,使用一个新的字符串result来保存我们截取到的并且长度最长的回文串。

代码:

public String longestPalindrome_reconstructure1(String s){ // 超出时间限制
        if (s.length() < 2){
            return s;
        }
        String result = s.substring(0,1);
        String temp = null;
        String temp1 = null;
        for(int i = 0; i < s.length() - 1; i++){
            temp = null;
            temp1 = null;
            for (int j = s.length(); j > i; j--){
                if (j - i < result.length()) break;
                temp = s.substring(i, j);
                temp1 = new StringBuilder(temp).reverse().toString(); // 对截取后的字符串进行反转

                if (temp.equals(temp1) && temp.length() > result.length()){
                    result = temp;
                }
            }
        }
        return result;
    }

上述代码倒是完成了得到最长回文子串的功能,但是,有个很明显的缺点就是时间开销太大了,所以肯定得想想办法减小时间开销

使用中心扩展算法:

我们观察到回文中心的两侧互为镜像。因此,回文可以从它的中心展开,并且只有 2n - 1个这样的中心。

你可能会问,为什么会是 2n - 1 个,而不是 n个中心?原因在于所含字母数为偶数的回文的中心可以处于两字母之间(例如 :“abba” 的中心在两个b之间),时间复杂度也只有O(n?2??)

代码:

// 使用中心扩展算法
    public String longestPalindrome_reconstructure2(String s) { // 第二次对代码进行重构
        if (s.length() < 2) { // 单个字符肯定是回文串,直接返回s
            return s;
        }
        int maxLength = 0;
        int center = 0;
        for (int i = 0; i < s.length(); i++){
            int begin = centerExpand(s, i, i);          // 最长回文串长度为奇数
            int end = centerExpand(s, i, i + 1);   // 最长回文串长度为偶数

            if (maxLength < Math.max(begin, end)){
                center = i;                                // 以center为中心
                maxLength = Math.max(begin, end);          // 最长回文串长度
            }
        }
        // 如果我们的回文串的长度为偶数,那么中心左边的长度会比右边的长度小1
        return s.substring(center - (maxLength - 1) / 2, center + maxLength / 2 + 1);
    }

    int centerExpand(String s, int begin, int end){
        int left = begin, right = end;
        while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)){
            left--;
            right++;
        }
        // 返回以begin,end为基准,同时向左向右扩展后能够得到的最长回文串长度
        return right - left - 1;
    }

使用动态规划法:

避免在验证回文时进行不必要的重复计算。考虑 “ababa” 这个示例。如果我们已经知道 “bab” 是回文,那么很明显,“ababa” 一定是回文,因为它的左首字母和右尾字母是相同的。

P(i,j)=(P(i+1,j?1) and S?i??==S?j??)

我们首先初始化一字母和二字母的回文,然后找到所有三字母回文,并依此类推…

代码:

// 使用动态规划法
    public String longestPalindrome_reconstructure3(String s) { // 第三次对代码进行重构
        if (s.length() < 2) { // 单个字符肯定是回文串,直接返回s
            return s;
        }
        boolean[][] dp = new boolean[s.length()][s.length()];  // 初始化一个二维数组,值默认是false
        String result = s.substring(0,1);
        for (int j = 0; j < s.length(); j++){
            for (int i = 0; i <= j; i++){
                dp[i][j] = s.charAt(i) == s.charAt(j) &&(j - i <= 2 || dp[i+1][j-1]);
                if (dp[i][j]){
                    if (j - i + 1 > result.length()){
                        result = s.substring(i, j + 1);
                    }
                }
            }
        }
        return result;
    }

原文地址:https://www.cnblogs.com/daleyzou/p/9393124.html

时间: 2024-08-29 23:11:51

最长回文子串 (动态规划法、中心扩展算法)的相关文章

hdu5371 最长回文子串变形(Manacher算法)

http://acm.hdu.edu.cn/showproblem.php? pid=5371 Problem Description Hotaru Ichijou recently is addicated to math problems. Now she is playing with N-sequence. Let's define N-sequence, which is composed with three parts and satisfied with the followin

51nod 1089 最长回文子串 V2(Manacher算法)

1089 最长回文子串 V2(Manacher算法) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 回文串是指aba.abba.cccbccc.aaaa这种左右对称的字符串. 输入一个字符串Str,输出Str里最长回文子串的长度. Input 输入Str(Str的长度 <= 100000) Output 输出最长回文子串的长度L. Input示例 daabaac Output示例 5 #include <iostream> #include

【回文字符串】 最长回文子串O(N) Manacher算法

原理讲的清晰:Manacher's ALGORITHM: O(n)时间求字符串的最长回文子串 注意: ①动态生命P[]和newStr数组后,不要忘记delete[] //其实这是基本的编码习惯 ②最终返回结果是P[i]-1 下面是自己写的Manacher函数 int manacher(char *src){ int srcLen=strlen(src); int len=2*srcLen+2; char *newStr=new char[len];//还是+3??要不要给\0留个位置??不用 i

【51NOD-0】1089 最长回文子串 V2(Manacher算法)

[算法]回文树 #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=100010; struct trees{int len,fail,t[260];}t[maxn]; char s[maxn]; int n,len,l,sz,ans; int getfail(int x) { while(s[len-t[x].len-1]!=s[len])

Manacher算法——最长回文子串(O(n))

1 public static int Manacher(String A,int n){ 2 char AA[]=A.toCharArray(); 3 char BB[]=new char[2*n+3]; 4 int k=0; 5 for(int i=1;i<=2*n+1;i=i+2){ 6 BB[i]='#'; 7 if(i+1<=2*n+1)BB[i+1]=AA[k++]; 8 } 9 BB[0]='$';//防止数组越界 10 BB[2*n+2]='&';//防止数组越界 11

最长回文子串(python)

又开始刷题了,去年被这道题虐过,今天终于写了一个还能看的版本. 这个版本肯定不是最优,这篇博客主要记录一下解题的过程,反思如何构思代码. 最长回文子串 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/longest-palindromic-substring 难度:中等(我觉得这题完全配得上困难) 题目: 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设?s 的最大长度为 1000. 示例 1: 输入: "babad"

51nod1089最长回文子串V2

1089 最长回文子串 V2(Manacher算法) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 回文串是指aba.abba.cccbccc.aaaa这种左右对称的字符串. 输入一个字符串Str,输出Str里最长回文子串的长度. Input 输入Str(Str的长度 <= 100000) Output 输出最长回文子串的长度L. Input示例 daabaac Output示例 5 看到这道题才特意去看了下Manacher算法:参考博客:http://blog.

1089 最长回文子串

1089 最长回文子串 V2(Manacher算法) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 回文串是指aba.abba.cccbccc.aaaa这种左右对称的字符串. 输入一个字符串Str,输出Str里最长回文子串的长度. Input 输入Str(Str的长度 <= 100000) Output 输出最长回文子串的长度L. Input示例 daabaac Output示例 5 马拉车算法的模板题也算是又进一步理解马拉车算法了. 1 //马拉车算法 2 #i

最长回文子串(动规,中心扩散法,Manacher算法)

题目 leetcode:5.?Longest Palindromic Substring 解法 动态规划 时间复杂度\(O(n^2)\),空间复杂度\(O(n^2)\) 基本解法直接看代码 class Solution { public: string longestPalindrome(string s) { int n = s.size(); vector<vector<bool>> dp(n, vector<bool>(n, true)); int rx, ry;