字符串专题总结

文章目录

    • 1.回文串
    • 2.最长连续公共子串 与 最长连续公共子序列
    • 3.字符串模式匹配 KMP算法

1.回文串

回文串包括一系列的题目,例如:求一个字符串中回文串的个数,求一个字符串中回文串的最大长度,求一个回文串中最长的回文串。其实只要掌握了高效判断字符串是否是回文串的方法,这类题目就迎刃而解了。

判断是否是回文串的方法:

  • 暴力:对于字符串的每一个子串进行判断是否回文,时间复杂度O(n^3),不推荐
  • 动态规划:dp[i][j] 以 下标 i 开始 下标 j 结束的字符串是否是回文串 ,可以基于其之前的结果进行断定 ,取决于(dp[i - 1][j - 1] 以及 str[i] == str[j]),要特殊判断下子串长度为1和2的情况。时间复杂度O(n^2)
  • 中心扩展法:以每个字符为中心向两端扩展,分别统计以下标为 i 的字符 和 (i, i + 1)这两个字符向两端扩展的情况,时间复杂度O(n^2)
  • 马拉车算法:时间复杂度 O(n)

具体参考:
leetcode409. 最长回文串:https://blog.csdn.net/qq_31672701/article/details/104973232
leetcode647.回文子串:https://blog.csdn.net/qq_31672701/article/details/104491890
leetcode5.最长回文子串:https://blog.csdn.net/qq_31672701/article/details/102886866


2.最长连续公共子串 与 最长连续公共子序列

首先要区分开这两个题目,也就是要明白子串和子序列的区别:

  • 子串:字符串中任意连续的每个字符串。例如:“abcd” ,有子串:“abc”,“bcd”,这仅仅是长度为3的子串,当然也有长度为1,2,4的,这里就不再一一列举了
  • 子序列:字符串中任意按照原序构成的成为子序列。例如:“abcd”,有子序列:“ad”,“ab”,“ac”等等。

处理这两个问题的方法都是动态规划,但是二者的数组的含义和状态转移方程的区别。

假设有两个字符串str1和str2.

最长公共子串

  • dp[i][j]:str1中以下标 i 结尾的子串和str2中以下标 j 结尾的子串,所能构成的最长公共子串
  • 状态转移方程:如果str1[i] == str2[j] 两个字符相等,dp[i][j] = dp[i - 1][j - 1] + 1;否则 dp[i][j] = 0

说明:按照动态规划的方法求出了最长公共子串的长度,可以寻找该长度在dp中的位置,来找出该子串,但要注意,该子串可能不止1个。

最长公共子序列

  • dp[i][j]:str1中以下标 i 结尾的子串str1[0…i]和str2中以下标 j 结尾的子串str2[0…j],所能构成的最长公共子序列。(注意:这个子序列并不一定以下标 i 或者下标 j 对应的字符结尾,而最长公共子串中,子串一定要以这个字符结尾)
  • 状态转移方程:如果str1[i] == str2[j] 两个字符相等,这个字符是公共子序列的一部分;否则,要么其中一个是子序列的一部分,要么都不是子序列的一部分,dp[i][j] = dp[i - 1][j - 1] + 1;否则 dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])

代码参考:https://blog.csdn.net/qq_31672701/article/details/102897026


3.字符串模式匹配 KMP算法

在主串T中找到子串P(模式串)的起始位置。
KMP算法是对暴力算法的优化,暴力算法是从主串T的每一个字符开始匹配,如果不成功则继续从主串的下一个位置和子串的开始位置进行匹配。暴力算法会涉及到主串和子串的多次回溯操作,而KMP只会一次扫描主串只回溯子串即可达到目标,其核心在于next数组来重置子串的下标位置保证主串不需要回溯。

KMP算法过程:

  • 从头开始匹配主串和子串,如果主串和子串对应字符相等,指向两个串的下标都往后移动一个位置
  • 如果两个字符不想等,主串下标不变,子串下标编程next数组对应位置指示的下标
  • 求next数组的过程?
    • 定义两个指针k, j,初始时k = -1, j = 0, 两个指针分别指向前缀串和后缀串的末尾,next[0] = -1
    • 如果 k = -1 或者p[k] = p[j],还需判断下p[k + 1] 和 p[j + 1]是否相等,以免产生多余的回溯;
      如果p[k + 1] == p[j + 1], next[j + 1] = next[k + 1];
      否则 next[j + 1] = k + 1
    • 如果p[k] != p[j], k = next[k],这里类似KMP中主串和子串的匹配过程,后缀串相当于子串,前缀串相当于子串

详细内容参考:https://blog.csdn.net/qq_31672701/article/details/105119562

拓展:字节的笔试题 本质是求字符串的周期,可以借助KMP算法的next数组的求法,来求周期。
详细参考:https://blog.csdn.net/qq_31672701/article/details/105121514

你可能感兴趣的:(#,leetcode总结)