总结在LeetCode中字符串相关的常用的一些算法
KMP 算法
KMP算法解决的是两个字符串的匹配问题(一个字符串是不是另外一个字符串的子串)
暴力法所需要的时间复杂度是O(n*m),KMP算法能够优化到O(n)。KMP算法的核心是使用一个next数组实现匹配的加速
next数组
最长前缀后缀:一个字符串中所有的前缀和其所有的后缀中最长的相等的长度,比如说“abcabc”的最长前缀后缀为”abc”
给定一个串s的next数组next[],其每一位next[i]表示串s[0…i-1]中最长前缀后缀
使用next数据对字符串匹配进行加速:s1中查找是否有子串s2,如果s1[i]匹配到s2[j]的时候不相等,并且此时next[j]=k,此时不需要重新回到s1[1]继续进行匹配,而是用s2[k]继续和s1[i]进行匹配,依次类推
因为next数组是找到了最长前缀后缀的,所以其能够从最长前缀的匹配跳到最长后缀的匹配,因为中间不可能出现匹配的情况,如果出现匹配那么表示当前next计算的不可能是”最长“前缀后缀。
next数组求法
规定next[0] = -1
, 因为其前面没有字符串;next[1] = 0
,因为其前面的字符串中只有一个字符,后面的next值的计算取决于前面的next值:
判断当前位置的字符和最长前缀的后一个字符是否相等,如果相等则next[i] = next[i-1] + 1
,如果不等再判断最长前缀的最长前缀和其相等不相等,如果还不相等就继续找最长前缀,直到最长前缀长度为0的时候表示没有找到,这个时候next[i] = 0
LeetCode 028
1 | class Solution { |
Manacher 算法
Manacher 算法解决的是字符串中最长的回文子串的问题
暴力法(技巧:中间添加辅助字符)解决这个问题的时间复杂度为O(n^2),Manacher算法能够时间复杂度优化为O(n)
几个概念
- 回文半径数组,以i为中心的的回文的半径长度
- 回文右边界,遍历过的回文能够达到的最右的下标
- 右边界中心位置,回文右边界对应的回文中心点下标
算法过程
和暴力解法一样从左向右扩充判断,有以下几种情况:
- 当前位置不在回文右边界里面,暴力扩充
- 当前位置在回文右边界里面,其关于右边界中心的对称点的回文区域在左边界里面,其回文半径和其对称点一样
- 当前位置在回文右边界里面,其关于右边界中心的对称点的回文左区域超过回文左边界,其回文半径为r-i
- 当前位置在回文右边界里面,其关于右边界中心的对称点的回文左区域与回文左边界重合(压线),其回文半径需要在r-i的基础上往后判断
LeetCode 005
1 | class Solution { |