字符串算法

基础字符串算法

遍历字符串

const str = 'hello world'; for (let i = 0; i < str.length; i++) { console.log(str[i]); } for (const k of str) { console.log(k); } for (const k in str) { console.log(str[k]); }

Java 中字符串是不可变的,字符串比较使用 equals、equalsIgnoreCase 方法。

基础问题

转换成小写字母

最后一个单词的长度

宝石与石头

字符串中的第一个唯一字符

字符串转换整数 (atoi)

字符串操作问题

最长公共前缀

反转字符串

反转字符串 II

翻转字符串里的单词

反转字符串中的单词 III

仅仅反转字母

Anagram 异位词问题

有效的字母异位词

字母异位词分组

找到字符串中所有字母异位词

回文串问题

验证回文串

验证回文字符串 Ⅱ

最长回文子串

高级字符串算法

动态规划和字符串相结合。

公共子串、子序列

编辑距离

最长公共子序列

最长公共子串

最长回文子串

字符串 + 递归/DP

正则表达式匹配

通配符匹配

不同的子序列

字符串匹配算法

  • 暴力法(brute force)O(MN)
  • Rabin-Karp 算法
  • KMP 算法

Boye-Moore算法

Sunday算法

暴力法

function forceSearch (text, pattern) { const M = text.length, N = pattern.length; for (let i = 0; i < M - N + 1; i++) { let matched = true; for (let j = 0; j < N; j++) { if (text[i + j] !== pattern[j]) { matched = false; break; } } if (matched) return i; } return -1; }

Rabin-Karp 算法

  • 朴素算法中,我们需要挨个比较所有字符,才知道目标字符串是否包含子串。
  • 为了避免挨个字符对目标字符串和子串进行比较,我们可以尝试一次性判断两者是否相等。因此,我们需要一个好的哈希函数(hash function)。通过哈希函数,我们可以算出子串的哈希值,然后将它和目标字符串的子串的哈希值进行比较。这个新方法在速度上比暴力法有显著提升。

算法思想

  1. 假设子串的长度为 M(Pat),目标字符串的长度为 N(txt)
  2. 计算子串的 hash 值 hash_pat
  3. 计算目标字符串 txt 中的每个长度为 M 的子串的 hash 值(总共需要计算 N-M+1 次)
  4. 比较 hash 值,如果 hash 值不同,字符串必然不匹配,如果 hash 值相同,还需要使用朴素算法再次判断
function rabinKarpSearch (text, pattern) { const D = 256, Q = 9997; let N = text.length, M = pattern.length; let patHash = 0, txtHash = 0; for (let i = 0; i < M; i++) { patHash = (D * patHash + pattern[i].codePointAt(0)) % Q; txtHash = (D * txtHash + text[i].codePointAt(0)) % Q; } let highestPow = 1; // 256 ** (M - 1); for (let i = 0; i < M - 1; i++) { highestPow = (highestPow * D) % Q; } let i, j; for (i = 0; i < N - M + 1; i++) { if (patHash === txtHash) { for (j = 0; j < M; j++) { if (pattern[j] !== text[i + j]) break; } if (j === M) return i; } if (i < N - M) { txtHash = (D * (txtHash - text[i].codePointAt(0) * highestPow) + text[i + M].codePointAt(0)) % Q; if (txtHash < 0) { txtHash += Q; } } } return -1; }

KMP 算法

KMP 算法(Knuth-Morris-Pratt)的思想就是,当子串与目标字符串不匹配时,其实已经知道前面已经匹配成功的那一部分字符(包括子串与目标字符串)。KMP 算法会设法利用这个已知信息,不要把 “搜索位置” 移回已经比较过的位置,继续把它向后移,这样就会提高效率。

KMP 字符串匹配算法视频

字符串匹配的 KMP 算法