Manacher最大回文串算法代码


```java
import static jdk.nashorn.internal.objects.NativeMath.min;
public class Manacher {

    public StringBuffer solution(String str){
        char [] s=str.toCharArray();
        char [] snew=new char[2*s.length+3];//给字符的两边添加特殊字符,把偶回文变成奇回文。
        int j=0;
        snew[j++]='$';//头一个字符与其他特殊字符区别开来,防止 while(snew[i+num[i]]==snew[i-num[i]])超出边界。
        snew[j++]='#';
        for(int i=0;i<s.length;i++){
            snew[j++]=s[i];
            snew[j++]='#';
        }
        snew[j]='¥';//最后一个字符与其他特殊字符区别开来,防止 while(snew[i+num[i]]==snew[i-num[i]])超出边界。
        int []num=new int[snew.length];
        int Max=1;//最靠右的回文半径的坐标
        int flag=1;//拥有最靠右的回文半径字符的坐标
        int maxlength=0;//记录整个字符数组最长的回文半径(用来获取最长回文字符串)
        int p=0;//记录拥有整个字符数组最长的回文半径字符的坐标(用来获取最长回文字符串)
        StringBuffer stringBuffer=new StringBuffer();
       for (int i=1;i<snew.length-1;i++){//需要从i=1开始,否则i-num[i]会越界;
           num[i]=Max>i?(int)min(num[2*flag-i],Max-i):1;//核心语句,根据i是否在Max里面计算i的回文右半径。
           while(snew[i+num[i]]==snew[i-num[i]])//判断下一个字符是否构成回文
               num[i]++;
           if(Max<num[i]+i){
               Max=num[i];
               flag=i;
           }
           if(maxlength<num[i]){//记录整个字符数组最长的回文半径
               maxlength=num[i];
               p=i;//记录拥有整个字符数组最长的回文半径字符的坐标
           }
       }

       for(int i=p-maxlength+1;i<p+maxlength-1;i++){//根据最长的回文半径及其坐标求出最长的回文字符串
           if(snew[i]!='#'){
               stringBuffer.append(snew[i]);
           }
       }
        return stringBuffer;
    }
    public static void main(String[] args) {
        Manacher manacher=new Manacher();
        StringBuffer string=manacher.solution("dabagbaf");
        System.out.println(string);
    }
}

首先计算当前字符的最大回文半径r,分四种情况:

  1. i不在R里面;
  2. i对映的i’的r在左R中
  3. i对映的i’的r在超出左R
  4. i对映的i’的r在刚好在R的边界上

2,3两个情况一次判断即可得出结果,1,4两种情况还需判断后面的字符是否构成回文

下面代码是核心代码

       num[i]=Max>i?(int)min(num[2*flag-i],Max-i):1;
       while(snew[i+num[i]]==snew[i-num[i]])
           num[i]++;

最后注意边界赋值
因为snew[i+num[i]]==snew[i-num[i]]使得遍历数组不能从0开始,否则i-num[i]会越界。同理也不能遍历字符数组的最后一个字符,否则i+num[i]会越界。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值