最长回文子串 Java实现和原理

最长回文子串问题概述

最长回文子串问题是一个经典的字符串处理问题,它的目标是找到一个字符串中最长的回文子串。回文是指一个正读和反读都一样的字符串,如 "aba" 或 "level"。这个问题在计算机科学中具有重要的应用价值,如生物信息学中的基因序列分析、自然语言处理中的文本分析等。

问题的基本解法

暴力解法

最直接的方法是枚举字符串中的所有子串,并检查它们是否是回文。这种方法的时间复杂度为 O(n^3),其中 n 是字符串的长度,因为对于长度为 n 的字符串,有 O(n^2) 个子串,每个子串的检查都需要 O(n) 的时间。显然,这种方法在字符串较长时效率极低。

动态规划

动态规划是一种解决优化问题的有效方法。对于最长回文子串问题,我们可以定义一个二维数组 dp[i][j],表示从索引 i 到索引 j 的子串是否是回文。根据回文的定义,我们可以得到状态转移方程:

dp[i][j] = (s[i] == s[j]) && (j - i <= 2 || dp[i + 1][j - 1])

这里 s 是输入的字符串。这个方程表示,如果 s[i] 和 s[j] 相等,并且子串 s[i+1:j-1] 也是回文(或者 i 和 j 相邻,或者 i 和 j 之间只有一个字符),那么 s[i:j] 就是回文。这种方法的时间复杂度为 O(n^2),空间复杂度也为 O(n^2)。

中心扩展法

中心扩展法是一种更高效的解决方案。它的基本思想是,对于字符串中的每一个字符和每一对相邻的字符,都尝试以它们为中心向两边扩展,找到以它们为中心的最长回文子串。这种方法的时间复杂度为 O(n^2),但空间复杂度仅为 O(1),因为它只需要常数级别的额外空间来存储最长回文子串的起始和结束位置。

Java实现及原理

下面我们将使用中心扩展法来解决最长回文子串问题,并给出相应的 Java 实现。

Java实现
java 复制代码
public class LongestPalindromeSubstring {
    public 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 + 1) {
                start = i - (len - 1) / 2;
                end = i + len / 2;
            }
        }

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

    // 以 left 和 right 为中心向两边扩展,找到最长回文子串的长度
    private 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 - L - 1;
    }
}
原理解释

在上面的 Java 实现中,我们定义了一个 longestPalindrome 方法来找到最长回文子串。这个方法首先遍历字符串中的每个字符,并以每个字符和每对相邻的字符为中心,调用 expandAroundCenter 方法来找到以它们为中心的最长回文子串。

expandAroundCenter 方法使用两个指针 LR 来表示当前回文子串的左右边界。它从给定的中心位置开始,如果左右指针指向的字符相同,就向两边扩展。当左右指针指向的字符不再相同,或者左指针小于 0,或者右指针大于等于字符串长度时,扩展停止。最后,返回以当前中心扩展得到的回文子串的长度。

longestPalindrome 方法中,我们使用 startend 来记录最长回文子串

相关推荐
seabirdssss26 分钟前
使用Spring Boot DevTools快速重启功能
java·spring boot·后端
喂完待续35 分钟前
【序列晋升】29 Spring Cloud Task 微服务架构下的轻量级任务调度框架
java·spring·spring cloud·云原生·架构·big data·序列晋升
benben04437 分钟前
ReAct模式解读
java·ai
轮到我狗叫了1 小时前
牛客.小红的子串牛客.kotori和抽卡牛客.循环汉诺塔牛客.ruby和薯条
java·开发语言·算法
yudiandian20141 小时前
【QT 5.12.12 下载 Windows 版本】
开发语言·qt
高山有多高2 小时前
详解文件操作
c语言·开发语言·数据库·c++·算法
狂奔的sherry2 小时前
单例模式(巨通俗易懂)普通单例,懒汉单例的实现和区别,依赖注入......
开发语言·c++·单例模式
Volunteer Technology2 小时前
三高项目-缓存设计
java·spring·缓存·高并发·高可用·高数据量
EnigmaCoder2 小时前
【C++】引用的本质与高效应用
开发语言·c++
栗子~~3 小时前
bat脚本- 将jar 包批量安装到 Maven 本地仓库
java·maven·jar