Manacher算法
关键词
字符串、回文、子串、线性复杂度
用途
快速找到一个字符串的最大回文子串
复杂度
时间复杂度:O(N)
空间复杂度:O(N)
中心扩展法
过程
从头到尾遍历字符串,对于每个元素x:
从x开始向左右扩展,直到左右元素不相等或抵达字符串边界
复杂度
时间复杂度:O()
空间复杂度:O()
优化思路
考虑在从前往后遍历x时,前边迭代中的信息有可能对后边的迭代有帮助,因此可以想办法用到这些信息来减少复杂度。
Manacher算法
过程
- 在从前往后扩展x时,对于每个x,记录下它扩展了多少位,存放在数组d中。则我们只要求出d数组,就等于求出了所有的回文子串。
- 考虑对于一个回文字符串a,容易知道它是对称的。因此,设a[i],a[j]关于字符串的中心对称,那么a[i]和a[j]能够向左右扩展的位数,应该是一样的。
- 因此我们在进行中心扩展时,维持一个记录右边界最大的回文子串(通俗的讲,就是前边扩展的时候,把能扩展到最右边的子串给记下来)。
- 那么在进行后边的扩展时,如果这次的中心不在之前“维护的那个回文子串”里,我们就只能按一般地方法去中心扩展。但是如果它在之前“维护的那个回文子串”里,我们就可以利用第二条的结论,通过它对称位置记录的d,得到它在这个回文子串里的最大回文子串(注意理解,此处比较绕)
- 理解了上条,你会发现有点不对:我要求的是在整个字符串的最大回文子串,你只给我求出在之前“维护的那个子串”里的子串是怎么回事。
- 因此我们在进行了上一步的操作后,只需要从“维护的子串”的边界继续向外扩展就可以了。
参考资料
- OI Wiki, Manacher算法 [oi-wiki.org/string/mana…]