查询字符串中回文字符的最大长度-java

  1. 回文字符就是指的是正着读,反着读,都一样的字符串。比如‘abcbaqes’中的‘abcba’就是一个回文字符 长度为5

这题其实和查找数字中最大回文数长度的做法是一样的道理

一、两边收缩法

找到字符串的所有子串,遍历每一个子串以验证它们是否为回文串。一个子串由子串的起点和终点确定,因此对于一个长度为n的字符串,共有n^2个子串。这些子串的平均长度大约是n/2,因此这个解法的时间复杂度是O(n^3)

显然这种方法十分暴力。那么有没有更不耗时间的方法呢?

二、中心拓展法

由于我们的字符串是回文字符串,那么当我们选择到回文数中间的数时,判断左右两边的字符是否相等。如果相等的话继续判断更旁边的字符是否相等。如果不相等,记录下此时回文数的长度,和最大值比较。
以上面的方法,遍历每个字符为中心,最后输出结果即为最大回文数。

//核心算法
private static int p(String a) {
        int max = 0;
        for (int i = 0; i < a.length()-1; i++) {
            for (int j = 0; i-j>=0&&j+i<a.length(); j++) {  //当回文数为奇数时
                //i-j代表靠近左边距离为j的字符,i+j同理。
                if(a.charAt(i-j)!=a.charAt(i+j))
                {
                    break;
                }else {
                    max = max>(2*j+1)?max:(2*j+1); //2*j+1为当前奇数回文数的长度
                }
                //继续寻找旁边的相等字符
            }
            for (int j = 0; i-j>=0&&j+i+1<a.length(); j++) {  //当回文数为偶数时
                //i-j代表靠近左边距离为j的字符,i+j同理。
                if(a.charAt(i-j)!=a.charAt(i+j+1))
                {
                    break;
                }else {
                    max = max>(2*j+2)?max:(2*j+2); //2*j+1为当前奇数回文数的长度
                }
                //继续寻找旁边的相等字符
            }
        }
        return max; //返回最大回文数的长度
    }

这个算法稍微优化了一下我们上面的暴力求解,复杂度变成O( n2 n 2 )

动态规划

动态规划和上面马拉松的时间复杂度是一样的 没学过动态规划的同学可以看这里动态规划初步
3/28号更新

当我们字符串变得足够大的时候显然我们这样的算法是不行的。We can do it better

Manacher算法(马拉车算法)

主要算法思路在Manacher算法详解里可以看到,这里我们就直接讲思路
我们上面的几个算法中我们需要算出分两种情况,一种奇数,一种偶数。这样就要进行两次循环,浪费了时间。
马拉车算法,主要就是在每个字符中插入‘#’使他的回文数全部变成奇数,这样只用求解一种情况。例如:

aba->#a#b#a#

核心算法:

    private static int Manacher(String a) {
        int pos = 0;
        String T = init(a);
        char[] t = T.toCharArray();
         int mx = 0;
        for (int i = 1; i < t.length; i++) {
            if (mx > i) {
                p[i] = Math.min(p[2 * pos - i], mx - i);
            } else {
                p[i] = 1;
            }
            while (i+p[i]<t.length&&i-p[i]>0&&t[i-p[i]]==t[i+p[i]]) {
                p[i]++;
            }
            if(mx<p[i]+i)
            {
                pos = i;
                mx = p[i]+i;
            }
            max = Math.max(max,p[i]-1);
        }

        return max;
    }

这样的话我们的复杂度就由 n(o2) n ( o 2 ) 变成了线性的 n(o) n ( o )

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值