初级篇:
下面三个题做法一模一样:
HJ11 数字颠倒
HJ12 字符串反转
HJ106 字符逆序
解法:
定义一个结果值进行接收,反向遍历输入的字符串,拼接到结果字符串中即可。
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void (async function () {
while ((line = await readline())) {
let input = line.split("");
let reversed = "";
for (let i = input.length - 1; i >= 0; i--) {
reversed += input[i];
}
console.log(reversed);
}
})();
HJ75 公共子串计算
解法一:
设 dp[i][j]
表示以 s1[i-1]
和 s2[j-1]
结尾的最长公共子串的长度。状态转移方程如下:
- 如果
s1[i-1] === s2[j-1]
,则增加公共子串长度dp[i][j] = dp[i-1][j-1] + 1
。 - 如果不相等,则
dp[i][j] = 0
。
最终结果就是 dp
数组中的最大值。
时间复杂度O(m*n),空间复杂度O(m*n)
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void async function () {
const s1 = await readline();
const s2 = await readline();
const dp = Array(s1.length + 1).fill(0).map(() => Array(s2.length + 1).fill(0));
let maxLength = 0;
for (let i = 1; i <= s1.length; i++) {
for (let j = 1; j <= s2.length; j++) {
if (s1[i - 1] === s2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
maxLength = Math.max(maxLength, dp[i][j]);
} else {
dp[i][j] = 0;
}
}
}
console.log(maxLength)
}()
解法二:
需要在每个长度 len
下,比较两个字符串中的所有子串。
- 设定滑动窗口的长度
len
,从 1 到min(s1.length, s2.length)
依次增大。 - 对每一个长度
len
,从s1
和s2
中分别提取所有可能的子串。 - 对于
s1
的每一个子串,检查它是否存在于s2
中。如果存在,更新最大公共子串长度。
时间复杂度O(n^3),空间复杂度O(n)
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void async function () {
const s1 = await readline();
const s2 = await readline();
let maxLength = 0;
const minLen = Math.min(s1.length, s2.length);
for (let len = 1; len <= minLen; len++) {
let found = false;
for (let i