求解最长的回文子串

1.暴力法

找出所有子串,并且判断是否是回文子串,并且记录最长长度,算法复杂度为O(n^3),强烈不推荐。

2.对称求解法

遍历字符串每个位置,从每个位置向两边扩散,判断是否对称,算法复杂度为O(n^2),但是需要考虑长度为奇偶两种情况。

示例代码:

 public int longestPalindrome(String str) {
int length=str.length();
if(str==null||length<1) {
return 0;
}
int result=0;
int max=0;
//遍历所有位置
for(int i=0;i<length;i++) {
//考虑str长度为奇数的情况,j为两边移动的距离
for(int j=0;j<=i&&i+j<length;j++) {
if(str.charAt(i-j)!=str.charAt(i+j)) {
break;
}
max=j*2+1;
}
if(max>result) {
result=max;
}
//考虑str长度为偶数的情况,j为移动的距离
for(int j=0;j<=i&&i+j+1<length;j++) {
if(str.charAt(i-j)!=str.charAt(i+j+1)) {
break;
}
max=j*2+2;
}
if(max>result)
result=max;
}
return result;

}

3.Manacher算法

从解法2我们可以发现仍有很多子串被重复判断,所以就引入了Manacher算法。

第一个不同:首先Manacher算法为了解决奇偶问题在原字符串中插入了#符号,将字符串长度统一为奇数,例如将字符串abcbae扩充为#a#b#c#b#a#e#

第二个不同:Manacher算法引入了一个回文半径,即用一个数组保存每个字符的回文半径,回文半径初始化为1,(本身),求解回文半径方法见代码注释。

 public  int longestPalindrome(String str) {
    //扩充字符串
    StringBuilder str2 = new StringBuilder();
    str2.append('#');
    for (int i = 0; i < str.length(); i ++) {
        str2.append(str.charAt(i));
        str2.append('#');
    }
    //回文半径数组
    int [] rad = new int[str2.length()];
    // right表示已知的最长回文子串最右边缘坐标
    int right = -1;
    // center表示已知的最长回文子串中点坐标
    int center = -1;
    
    for (int i = 0; i < str2.length(); i ++) {
        //初始回文半径1,自己本身
        int r = 1;
        // 找到i的关于center对称位置j,j=2*center-i
        //如果对称位置的rad小于right-i,说明以j为中心的回文子串在已知最长回文子串中,由对称性可知,rad[i]=rad[j]
        //否则i的回文半径就是right-i,所以回文半径就是right-i,所以就相当于取两个的最小值,这种情况就需要再向两边进行匹配
        //进行这个判断的原因是为了省去重复字符串扫描
        if (i <= right) {
            r = Math.min(right-i, rad[2 * center - i]);
        }
        // 向两边进行匹配
        while (i - r >= 0 && i + r < str2.length() && str2.charAt(i - r) == str2.charAt(i + r)) {
            r++;
        }
        // 如果扫描结束后位置大于right,需要更新right和center
        if (i + r - 1> right) {
            right = i + r - 1;
            center = i;
        }
        rad[i] = r;
    }
    
    // 扫描最大长度
    int result = 0;
    for (int r : rad) {
        if (r > result) {
            result = r;
        }
    }
    return result - 1;
}

猜你喜欢

转载自blog.csdn.net/bathe123/article/details/79956945