【LeetCode】5.求最长回文子串

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

1.O(n^2)解法:
①定义一个二维辅助数组p,其中p[i][j]的含义:p[i][j] = s.substring(i,j+i) 是否是回文子串?1:0;
②初始情况:当i=j时,p[i][j] = 1; 当i=j-1时,p[i][j] = s[i]==s[j]?1:0;
③那么,现在的问题就是根据初始情况,来求p[i][j]了。根据回文串的特性,只有当p[i+1][j-1]为回文串时且s[i]=s[j]时,p[i][j]才是回文串;否则,p[i][j]不满足回文串特性。
④求得辅助数组p后,可求得回文子串中的最长回文串。
代码如下:

//最长回文子串
    public String longestPalindrome(String s) {
        int[][] dp = new int[s.length()][s.length()];
        int max_length = -1;
        int start = -1;
        int end = -1;
        for(int j=0;j<s.length();++j){
            for(int i = 0;i<=j;++i){
                if(i==j){
                    dp[i][j] = 1;
                }
                else if(i==j-1){
                    if(s.charAt(i)==s.charAt(j))
                        dp[i][j] = 1;
                }
                else if(dp[i+1][j-1]==1){
                    if(s.charAt(i)==s.charAt(j)){
                        dp[i][j] = 1;
                    }
                }
                if(dp[i][j]==1){
                    if(max_length<s.substring(i,j+1).length()){
                        start = i;
                        end = j+1;
                        max_length = s.substring(start,end).length();
                    }
                }
            }
        }

        if(start>=0)
            return s.substring(start,end);
        return "";
    }

2.Manacher 算法:具体思路可以点标题进去看,感觉这篇是我看到的讲得比较清晰的。
实现代码:

//最长回文子串 Manacher 算法
    public String Manacher(String s) {
        //奇偶处理
        char[] chars = new char[s.length()*2+3];
        chars[0] = '^';
        chars[s.length()*2+2] = '$';
        int j = 1;
        for(int i=0;i<s.length();++i){
            chars[j++] = '#';
            chars[j++] = s.charAt(i);
        }
        chars[j] = '#';
        
        int[] p = new int[chars.length];
        p[0] = 0;
        p[1] = 0;
        int Mi = 1;
        
        for(int i=2;i<chars.length-1;++i){
            int L = Mi-p[Mi];
            int R = Mi+p[Mi];
            if(i<R){
                j = 2*Mi-i;
                if(j-p[j]>L){
                    p[i] = p[j];
                }else{
                    p[i] = R-i-1;
                    int ir = R;
                    int il = 2*i-R;
                    while(ir>0&&ir<chars.length-1){
                        if(chars[ir]==chars[il]){
                            p[i]++;
                            ir++;
                            il--;
                        }else{
                            break;
                        }
                    }
                }
            }else{
                //按传统方法求解
                int il = i-1;
                int ir = i+1;
                while(ir>0&&ir<chars.length-1){
                    if(chars[ir]==chars[il]){
                        p[i]++;
                        ir++;
                        il--;
                    }else{
                        break;
                    }
                }
            }
            if(p[i]>p[Mi])
                Mi = i;
        }
        StringBuilder sb = new StringBuilder();
        for(int start = Mi-p[Mi];start<=Mi+p[Mi];++start){
            if(chars[start]!='#'){
                sb.append(chars[start]);
            }
        }
        return sb.toString();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值