1.两个字符串比较
寻找最大公共字符串
这里迷糊的点在于,根据 s1 s2 的长度去生成 dp 举证的 的长宽怎么确定,以及 for 循环怎么写。
一开始纠结这一点,其实,去还原过程就可以轻松得到。
1)固定s1(长度m),拿 s2 (长度n)中的每一字符 依次和 s2 的每个字符比较。每个结果都记录,会生成arr[n][m]
function getCommonString(s1, s2) {let m = s1.length;let n = s2.length;let dp = new Array(n).fill().map(() => new Array(m).fill(0));let max = 0;let range = [-1, -1];for (let i = 0; i < n; i++) {for (let j = 0; j < m; j++) {if (s1[i] === s2[j]) {if (i === 0 || j === 0) { // 边缘的处理,解决了纠结dp[i][j] = 1;} else {dp[i][j] = dp[i - 1][j - 1] + 1; // 一开始看起来并不是动规,而是一种归类}if (max < dp[i][j]) {max = dp[i][j];range = [j + 1 - dp[i][j], j];}}}}return s1.slice(range[0], range[1] + 1);}
这个还是看不明白。
来个能看明白的:
不需要考虑太多,只要知道:1)s1 长度为m 指针为i; 2) s2 长度为 n 指针为 j;
2) dp 第一圈都填0,dp[i][j] 代表子问题:text1[0…i] 和 text2[0…j] 最大公共子字符串的长度
function getCommonString(s1, s2) {let m = s1.length + 1;let n = s2.length + 1;// dp[i][j] 代表 text1[0...i] 和 text2[0...j] 最大公共子字符串的长度let dp = new Array(m).fill().map(() => new Array(n).fill(0));for (let i = 0; i < m; i++) {dp[i][0] = 0;}for (let j = 0; j < n; j++) {dp[0][j] = 0;}let max = 0;let end = 0;for (let i = 1; i < m; i++) {for (let j = 1; j < m; j++) {if (s1[i - 1] === s2[j - 1]) {dp[i][j] = dp[i - 1][j - 1] + 1;if (max < dp[i][j]) {max = dp[i][j];end = i;}}}}return s1.slice(end - max, end);// return s1.slice(end - max + 1, end + 1) // 注意要同时向回减一}
最长公共子序列
function longestCommonSubsequence(text1, text2) {let m = text1.length + 1;let n = text2.length + 1;// dp[i][j] 代表 text1[0...i] 和 text2[0...j] 最大公共子序列的长度// 当 i = 0 时,text1[0...0] 代表 text1 的空子符串,因此 当 i = m,text1[0...m] 代表全部的 text1。// 最终得出 dp.length 长度为 m + 1,而dp[0].length 为 n + 1。let dp = new Array(m).fill().map(() => new Array(n).fill(0));for (let i = 0; i < m; i++) {dp[i][0] = 0;}for (let j = 0; j < n; j++) {dp[0][j] = 0;}for (let i = 1; i < m; i++) {for (let j = 1; j < n; j++) {// dp[i][j] 代表 text1[0...i] 和 text2[0...j] 最大公共子序列的长度// 所以当前字符表示为 text1[i - 1] 和 text2[j - 1]if (text1[i - 1] === text2[j - 1]) { // 因为增加了边界,所以也要递减一个位置dp[i][j] = dp[i - 1][j - 1] + 1;} else {dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);}}}return dp[m - 1][n - 1]; // 结尾元素}

数组认为加出一道边界哈。
5. 最长回文子串
72. 编辑距离
参考视屏: https://www.bilibili.com/video/BV1uv411W73P/?spm_id_from=333.788.recommend_more_video.0
子问题的发掘简直是叼炸天呢:





js 写法:
var minDistance = function(word1, word2) {const m = word1.length;const n = word2.length;const dp = new Array(m + 1).fill(0).map(() => new Array(n + 1).fill(0));for (let i = 0; i <= m; i++) {dp[i][0] = i;}for (let j = 0; j <= n; j++) {dp[0][j] = j;}for (let i = 1; i <= m; i++) {for (let j = 1; j <=n; j++) {if (word1[i - 1] === word2[j - 1]) {dp[i][j] = dp[i - 1][j - 1];} else {dp[i][j] = Math.min(dp[i][j - 1] + 1, dp[i - 1][j] + 1, dp[i - 1][j - 1] + 1);}}}return dp[m][n];};
这题有点复杂了,但是作者还是很牛逼。
