LC 792. 匹配子序列的单词数 (opens new window) (opens new window)
中等
# 问题描述
给定字符串 s
和字符串数组 words
, 返回 words[i]
中是 s
的子序列的单词个数 。
字符串的 子序列 是从原始字符串中生成的新字符串,可以从中删去一些字符(可以是 none),而不改变其余字符的相对顺序。
- 例如,
“ace”
是“abcde”
的子序列。
示例 1:
输入: s = "abcde", words = ["a","bb","acd","ace"]
输出: 3
解释: 有三个是 s 的子序列的单词: "a", "acd", "ace"。
示例 2:
输入: s = "dsahjpjauf", words = ["ahjpjau","ja","ahbwzgqnuk","tnmlanowax"]
输出: 2
提示:
1 <= s.length <= 5 * 104
1 <= words.length <= 5000
1 <= words[i].length <= 50
words[i]
和s
都只由小写字母组成。
# 二分查找
对字符进行预处理,记录每个字母所在的下标,然后遍历数组中的每个字符串,对于每个字母,从预处理结果中查找其下标,若该字母存在一个下标与比当前下标更大,则返回最接近的最大下标,如果该字符串能够一直找到下一个更大的下标,直到字符串遍历完毕,说明该字符串为原字符传的子序列,则否说明该字符串不为原字符串的子序列。
/**
* @param {string} s
* @param {string[]} words
* @return {number}
*/
var numMatchingSubseq = function (s, words) {
const pos = new Array(26).fill(0).map(() => [])
for (let i = 0; i < s.length; i++) {
pos[s.charCodeAt(i) - 97].push(i)
}
const binarySearch = (arr, target) => {
if (arr.length === 0) return -1
if (target >= arr[arr.length - 1]) return -1
let l = 0
let r = arr.length - 1
while (l < r) {
const mid = (l + r) >> 1
if (arr[mid] <= target) {
l = mid + 1
} else {
r = mid
}
}
return arr[l]
}
let ans = words.length
for (const word of words) {
if (word.length <= s.length) {
let p = -1
for (const c of word) {
p = binarySearch(pos[c.charCodeAt(0) - 97], p)
if (p === -1) {
ans--
break
}
}
}
}
return ans
}
- 时间复杂度:
- 空间复杂度:
上次更新: 2023/01/31 19:48:05
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 , 转载请注明出处!