笔试复盘 - 最长回文子串

回文串的经典题型:最长回文子串

回文串的长度可能是奇数,也可能是偶数,所以要分开考虑
ABBA: 回文中心是BB之间的间隙;ABA:回文中心是B

  1. 为了简单化问题我们可以用一个字符串中没出现过的字符来进行填充,让它都变成长度为奇数的串,如#A#B#B#A#(后面都以此为例)
  2. 然后再利用中心扩散的思想,求解
    以str[0]为回文中心是,左边扩散是边界,右边是A,故它能扩散0步
    我们可以填这样一个表
ch#A#B#B#A#
index012345678
p010141010

观察发现,最长回文子串就是p数组的最大值

function solution(str) {
    str = '#' + str.split('').join('#') + '#';
    let len = str.length;
    const p = new Array(len);
    const fn = (index) => {
        let i = index - 1, j = index + 1;
        let step = 0;
        while(i >= 0 && j < len && str[i] === str[j]){
            i--;
            j++;
            step++;
        }
        return step;
    };
    for(let i = 0; i < len; i++){
        p[i] = fn(i);
    }
    return Math.max(...p);
}

扩展一下,如果是带有*号的字符串,*表示任意一个字母,只需要修改一下中心扩散的判定条件即可

console.log(solution('DAB*B*ACD'));

function solution(str) {
    str = '#' + str.split('').join('#') + '#';
    let len = str.length;
    const p = new Array(len);
    const fn = (index) => {
        let i = index - 1, j = index + 1;
        let step = 0;
        while(i >= 0 && j < len){
            if(str[i] === str[j] || (str[i] === '*' || str[j] === '*')){
                i--;
                j++;
                step++;
            }
            else break;
        }
        return step;
    };
    for(let i = 0; i < len; i++){
        p[i] = fn(i);
    }
    return Math.max(...p);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值