leetcode——最长回文(马拉车)

17 篇文章 0 订阅

1、思想概述:
求最大回文长度,例如,adfaddddaerg中,可以把构成回文的就是adddda,故此字符串的最大回文长度为6.
回文:即一个字符串正着反着读都一样的,如上面说的adddda或noon等.
当我们求解此问题时,首先会想到暴力的遍历数组,枚举数组中所有字串,然后再进行比较,但是这样做它的时间复杂度达到了
O(n^3)
,十分不理想,所里这里提出了马拉车算法解决这个问题,可以将时间复杂度提升到**O(n)**的理想状态;
2、马拉车算法概述:
马拉车算法首先实在每个字符串中间插入了一个字符串中没有的字符,通常用#(首尾也插),这样就解决了中心点的落脚问题。因为当原本字符串为奇数时,中心点会落脚为字符串的原本中心点,当字符串为偶数个时,中心点落脚为#,这样就统意了字符串的奇偶数问题;然后再建立一个数组记录当前插入#后字符串的最大回文半径值。然后得到如下图所示。
在这里插入图片描述
代码实现

public static void main(String[] args) {
    
    Scanner in = new Scanner(System.in);

    String inStr = in.nextLine();

    manacher(inStr);



}



public static void manacher (String str){



    char [] cStr = str.toCharArray();

    StringBuffer sBuffer = new StringBuffer();

    sBuffer.append("#");

    for (int i = 0; i < cStr.length; i++) {

        sBuffer.append(cStr[i]);

        sBuffer.append("#");

    }

    int id =0;

    int max = 0;

    int p[]= new int[sBuffer.length()];

    for (int i = 1; i < sBuffer.length(); i++) {



        if (i<max) {

            p[i] = Math.min(p[2*id-i], max-i);

        }else {

            p[i]= 1;

        }

        while (i-p[i]>=0&&i+p[i]<sBuffer.length()&&sBuffer.charAt(i-p[i])==sBuffer.charAt(i+p[i])) {

            p[i]++;

        }

        if (i+p[i]>max) {

            max = i+p[i];

            id = i;

        }

    }

    int maxl = 0 ;

    int maxid =0 ;

    for(int i =0 ;i<p.length;i++){

        if(maxl<p[i]){

            maxl=p[i];

            maxid = i;

        }



    }

    int r = maxl-1;

    int start = maxid-r+1;

    int end = maxid+maxl-1;

    StringBuffer out = new StringBuffer();

    for (int i = start; i < end; i++) {

        if (sBuffer.charAt(i)!='#') {

            out.append(sBuffer.charAt(i));

        }

    }

    System.out.println( (maxl-1)+" "+out.toString());

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值