美文网首页
Manacher算法 求解最长回文子串

Manacher算法 求解最长回文子串

作者: futurehau | 来源:发表于2016-08-23 21:49 被阅读104次

求解一个字符串的最长回文子串

最朴素的想法是以每个点为中心向两边扩,看能扩多远,另外还需注意回文串长度为偶数1221时的问题。复杂度O(n^2),这里不再详细介绍,直接上代码

public class Solution {
    private int lo;
    private int max;
    public String longestPalindrome(String s) {
        if(s.length()<2)
            return s;
        for(int i=0;i<s.length()-1;i++){
            longestPalHelper(s,i,i);
            longestPalHelper(s,i,i+1);
        }
        return s.substring(lo,max+lo);
    }
    public void longestPalHelper(String s,int i,int j){
        while(i>=0 && j<s.length()&&s.charAt(i)==s.charAt(j)){
            i--;
            j++;
        }
        if(j-i-1>max){
            max=j-i-1;
            lo=i+1;
        }
    }
}

一个特殊处理技巧,先把原来的字符串扩大1221变为#1 #2#2#1#,这样就避免了分出情况讨论回文串长度为偶数,121 #1#2#1#,利用求得的长度除以2就是原来回文串的长度。(加上啥都行,不一定是# 例如上例可以是1也可以是2)
加上#之后的字符串为处理串,现在对处理串进行处理,具体过程如图片所示。

man.jpg

求回文串长度的代码

public static int longestPalindrome(String s) {
        StringBuilder sb=new StringBuilder();
        sb.append("#");
        for(int i=0;i<s.length();i++){
            sb.append(s.charAt(i));
            sb.append("#");
        }
        String newString=sb.toString();
        int[] PArr=new int[newString.length()];
        int PR=0;
        int index=0;
        int max=0;
        for(int i=0;i<PArr.length;i++){
            if(i<PR){
                int i1=2*index-i;
                int smallR=PArr[i1];
                int leftSmall=i1-smallR+1;
                int leftBig=index-PArr[index]+1;
                if(leftSmall>leftBig)
                    PArr[i]=smallR;
                else if(leftSmall<leftBig){
                    PArr[i]=PR-i;
                }
                else{
                    int r=smallR;
                    while(i-r>=0&&i+r<PArr.length&&newString.charAt(i-r)==newString.charAt(i+r)){
                        r++;
                    }
                    PArr[i]=r;
                    PR=i+r;
                    index=i;
                }
            }
            else{
                int r=1;
                while(i-r>=0&&i+r<PArr.length&&newString.charAt(i-r)==newString.charAt(i+r)){
                    r++;
                }
                PArr[i]=r;
                PR=i+r;
                index=i;
            }
            max=Math.max(max,PArr[i]);
        }
        return max-1;
    }

求最长回文子串
[leetcode5]https://leetcode.com/problems/longest-palindromic-substring/
使用Manacher算法

public class Solution {
     public String longestPalindrome(String s) {
        StringBuilder sb=new StringBuilder();
        sb.append("#");
        for(int i=0;i<s.length();i++){
            sb.append(s.charAt(i));
            sb.append("#");
        }
        String newString=sb.toString();
        int[] PArr=new int[newString.length()];
        int PR=0;
        int index=0;
        int max=0;
        int maxIndex=0;
        for(int i=0;i<PArr.length;i++){
            if(i<PR){
                int i1=2*index-i;
                int smallR=PArr[i1];
                int leftSmall=i1-smallR+1;
                int leftBig=index-PArr[index]+1;
                if(leftSmall>leftBig)
                    PArr[i]=smallR;
                else if(leftSmall<leftBig){
                    PArr[i]=PR-i;
                }
                else{
                    int r=smallR;
                    while(i-r>=0&&i+r<PArr.length&&newString.charAt(i-r)==newString.charAt(i+r)){
                        r++;
                    }
                    PArr[i]=r;
                    PR=i+r;
                    index=i;
                }
            }
            else{
                int r=1;
                while(i-r>=0&&i+r<PArr.length&&newString.charAt(i-r)==newString.charAt(i+r)){
                    r++;
                }
                PArr[i]=r;
                PR=i+r;
                index=i;
            }
            if(PArr[i]>max){
                max=PArr[i];
                maxIndex=index;
            }
        }
        StringBuilder stringBuilder=new StringBuilder();
        int begin=maxIndex-max+1;
        int end=maxIndex+max-1;
        for(int i=begin+1;i<=end;i+=2){
            stringBuilder.append(newString.charAt(i));
        }
        return stringBuilder.toString();
    }
}

从学习Manacher算法到现在把代码实现,用了整整一晚上的时间,leetcode上accept的那一刻很开心,继续加油!

相关文章

  • Manacher算法

    前言 Manacher算法用于求解字符串中最长的回文子串,它和KMP算法的改进方式很类似,都是基于暴力求解的方法,...

  • Manacher's Algorithm算法分析Java

    Manacher's Algorithm俗称马拉车算法,对于求字符串中最长回文子串效率极高。 在求最长回文子串的时...

  • 最长回文子串

    最长回文子串——Manacher 算法 1. 问题定义 最长回文字符串问题:给定一个字符串,求它的最长回文子串长度...

  • Manacher算法求解最长回文子串

    一、背景 最近在LintCode上面刷题时遇到了一个求解最长回文子串的问题,这个题目可以使用暴力的方式去进行求解,...

  • Manacher算法 求解最长回文子串

    求解一个字符串的最长回文子串 最朴素的想法是以每个点为中心向两边扩,看能扩多远,另外还需注意回文串长度为偶数122...

  • 经典算法问题:最长回文子串之 Manacher 算法

    title: 经典算法问题:最长回文子串之 Manacher 算法date: 2019-02-17 08:00:0...

  • Manacher算法的详细讲解

    Manacher算法,又叫“马拉车”算法,可以在时间复杂度为O(n)的情况下求解一个字符串的最长回文子串长度的问题...

  • Manacher算法详解

    目录结构如下: 引入 Manacher算法详解 例题 References 1. 问题引入 最长回文子串(Long...

  • Manacher's algorithm

    Manacher算法主要解决的问题是求给定字符串中最长的回文字符串。 以前咱们求解回文字符串的步骤是找中心点, ...

  • 最长回文子串

    最长回文子串 public class Manacher { public static int min(int ...

网友评论

      本文标题:Manacher算法 求解最长回文子串

      本文链接:https://www.haomeiwen.com/subject/ppsnsttx.html