214.最短回文子串KMP解法浅析(Leetcode)

题目:214最短回文子串:给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。

在官方给的题解中,暴力法与双指针递归解法的时间复杂度为O(n2),最后有一个神奇的KMP(Knuth–Morris–Pratt) 算法实现了O(n)的复杂度,如此牛X,自然要仔细学学,遂先去学了下KMP算法,在此推荐一个知乎的讲解:

https://zhuanlan.zhihu.com/p/83334559

然而神奇的是,即使我自认为看懂了KMP算法,转过头一时竟也没看懂leetcode的解法,费了老鼻子劲才想通,不得不说leetcode上许多解法真的骚,卵秀飞,故在此做个思路记录(以各位了解KMP算法为前提)。

我们知道KMP算法可以理解为一种动态规划,其相应的dp数组称作确定有限状态自动机(也称部分匹配表),在KMP算法中,我们的目标是在文本串中找到目标串的位置,而状态机记录了与当前读取的字符串具有相同前缀的最长子串(我们这里取个名字叫影子子串,其状态为影子状态),当前的下一字符不匹配时,我们通过状态机返回影子状态,这样就可以免去回溯,大大提高效率。注意这个状态机是只与目标串有关的,也即在确定目标串时,其状态机也已确认。

 而该题的KMP解法实际上就是单独使用了这个状态机。首先我们很容易得到的解题思路是,我们只需得到输入从字符串起始位置开始的最大回文子串,那么如何得到该回文子串呢?如果我们将一串字符与其反转(reversed)拼接在一起,并在其中加一个分隔符以示区别,如cbcad和其反转dacbc,及分隔符“#”构成了cbcad#dacbc。我们对该字符应用KMP算法构建其状态机,那么对于该字符串的匹配状态,也即最后一个字符c,其对应的影子子串的最后一个字符就是整个字符的位置2处的c,因为当构成回文时,反转部分的后缀必定与原字符对应部分的前缀相同。这样我们就能够通过寻找状态机匹配状态时的影子状态的位置来得到最大回文子串了。

另外分隔符时必须的,否则如aaa这种,构成一个aaaaaa的字符串,那么影子子串的长度即为5,显然不行。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值