最长回文子串

在这里插入图片描述

//使用manacher算法
//首先将字符串 扩成#a#b#c#... 这样就可以消除 奇数偶数的问题
//通过 最大半径和中心值 找到最长回文
//其中 有一个至少不用比较的区域 然后再通过这个区域 慢慢像两边扩
//至少不用比较的区域:通过是否落在之前R范围内来判断
//1、当i落在R之外,不用比较的就只有自己本身了
//2、当i落在R里,那就是与i对称 ii的不用比较区域
//3、当i落在R上,就是i到R的距离,作为不用比较区域
//不断更新半径和中心值
class Solution {
//使用manacher算法
//首先将字符串 扩成#a#b#c#... 这样就可以消除 奇数偶数的问题
//通过 最大半径和中心值 找到最长回文
//其中 有一个至少不用比较的区域 然后再通过这个区域 慢慢像两边扩
//至少不用比较的区域:通过是否落在之前R范围内来判断
//1、当i落在R之外,不用比较的就只有自己本身了
//2、当i落在R里,那就是与i对称 ii的不用比较区域
//3、当i落在R上,就是i到R的距离,作为不用比较区域
//不断更新半径和中心值
    public String longestPalindrome(String s) {
        if(s.length()==0||s.length()==1){
            return s;
        }
        return lenPalindrome(s).replace("#", "");
    }
    public static String changeString(String s){
        String str="#";
        for(int i=0;i<s.length();i++){
            str+=s.charAt(i)+"#";
        }
        return str;

    }

    
    public static String lenPalindrome(String s){//最大回文长度
        String str=changeString(s);
        ///记录至少不用比较的区域 的值(每一个点的半径)
        int []nArea=new int[str.length()];
        int R=-1;//最大半径
        int C=-1;//中心点
      
        // int max=-1;//找到向外扩最大的值 
        for(int i=0;i<str.length();i++){
            ///每个点对应的至少不用比较区域(最小半径)
            nArea[i]=R>i ?   Math.min(nArea[2*C-i],R-i):1;
            ///填入值 半径边界问题
            while(i+nArea[i]<str.length()&&i-nArea[i]>-1){
                if(str.charAt(i+nArea[i])==str.charAt(i-nArea[i])){//如果半径 左右的值相同, 最大不用比较区域的值++ 然后需要和之前的R比较 
                    nArea[i]++;
                }else{
                    break;
            }///这个循环结束 也就是 找到了这个点向外扩的最大值
            需要找到所有点中最大半径 和对应的C
            if(i+nArea[i]>R){
                R=nArea[i]+i;
                C=i;
               

            }
            // max=Math.max(max,nArea[i]);//记录了向外扩的最大值

        }

        由于 这个字符串是之前处理过的,有个规律就是 处理前的最大长度 就是往外扩最大值-1
    }
      ///由于需要返回字符串,因为nArea 里面记录每一个点往外扩的最大值 需要找到最大值 和当时的点
        int m=-1;
        int start=-1;
        for(int k=0;k<nArea.length;k++){
            if(m<nArea[k]){
                start=k;
                m=nArea[k];
            }
        }///返回开始的中心点 和往外扩的最大值
       return str.substring(start-m+1,start+m);
		
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值