列表

详情


3297. 统计重新排列后包含另一个字符串的子字符串数目 I

给你两个字符串 word1 和 word2 。

如果一个字符串 x 重新排列后,word2 是重排字符串的 前缀 ,那么我们称字符串 x 是 合法的 。

请你返回 word1 中 合法 子字符串 的数目。

 

示例 1:

输入:word1 = "bcca", word2 = "abc"

输出:1

解释:

唯一合法的子字符串是 "bcca" ,可以重新排列得到 "abcc" ,"abc" 是它的前缀。

示例 2:

输入:word1 = "abcabc", word2 = "abc"

输出:10

解释:

除了长度为 1 和 2 的所有子字符串都是合法的。

示例 3:

输入:word1 = "abcabc", word2 = "aaabc"

输出:0

 

解释:

相似题目

最小覆盖子串

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: long long validSubstringCount(string word1, string word2) { } };

rust 解法, 执行用时: 0 ms, 内存消耗: 2.5 MB, 提交时间: 2025-01-09 09:18:49

impl Solution {
    pub fn valid_substring_count(s: String, t: String) -> i64 {
        if s.len() < t.len() {
            return 0;
        }

        let mut diff = vec![0; 26]; // t 的字母出现次数与 s 的字母出现次数之差
        for c in t.bytes() {
            diff[(c - b'a') as usize] += 1;
        }

        // 统计窗口内有多少个字母的出现次数比 t 的少
        let mut less = diff.iter().filter(|&&d| d > 0).count() as i32;

        let mut ans = 0;
        let mut left = 0;
        let s = s.as_bytes();
        for c in s {
            let c = (c - b'a') as usize;
            diff[c] -= 1;
            if diff[c] == 0 {
                // c 移入窗口后,窗口内 c 的出现次数和 t 的一样
                less -= 1;
            }
            while less == 0 { // 窗口符合要求
                let out_char = (s[left] - b'a') as usize; // 准备移出窗口的字母
                if diff[out_char] == 0 {
                    // out_char 移出窗口之前,检查出现次数,
                    // 如果窗口内 out_char 的出现次数和 t 的一样,
                    // 那么 out_char 移出窗口后,窗口内 out_char 的出现次数比 t 的少
                    less += 1;
                }
                diff[out_char] += 1;
                left += 1;
            }
            ans += left;
        }
        ans as _
    }
}

javascript 解法, 执行用时: 31 ms, 内存消耗: 57.3 MB, 提交时间: 2025-01-09 09:18:34

/**
 * @param {string} word1
 * @param {string} word2
 * @return {number}
 */
var validSubstringCount = function(s, t) {
    if (s.length < t.length) {
        return 0;
    }

    const diff = Array(26).fill(0); // t 的字母出现次数与 s 的字母出现次数之差
    for (const c of t) {
        diff[c.charCodeAt(0) - 'a'.charCodeAt(0)]++;
    }

    // 统计窗口内有多少个字母的出现次数比 t 的少
    let less = 0;
    for (const d of diff) {
        if (d > 0) {
            less++;
        }
    }

    let ans = 0;
    let left = 0;
    for (const ch of s) {
        const c = ch.charCodeAt(0) - 'a'.charCodeAt(0);
        diff[c]--;
        if (diff[c] === 0) {
            // c 移入窗口后,窗口内 c 的出现次数和 t 的一样
            less--;
        }
        while (less === 0) { // 窗口符合要求
            const outChar = s[left++].charCodeAt(0) - 'a'.charCodeAt(0);
            if (diff[outChar] === 0) {
                // outChar 移出窗口之前,检查出现次数,
                // 如果窗口内 outChar 的出现次数和 t 的一样,
                // 那么 outChar 移出窗口后,窗口内 outChar 的出现次数比 t 的少
                less++;
            }
            diff[outChar]++;
        }
        ans += left;
    }
    return ans;
};

python3 解法, 执行用时: 176 ms, 内存消耗: 16.9 MB, 提交时间: 2024-10-13 23:36:05

class Solution:
    def validSubstringCount(self, s: str, t: str) -> int:
        if len(s) < len(t):
            return 0

        # t 的字母出现次数与 s 的字母出现次数之差
        cnt = defaultdict(int)  # 也可以用 Counter(t),但是会慢很多
        for b in t:
            cnt[b] += 1
        # 窗口内有 less 个字母的出现次数比 t 的少
        less = len(cnt)

        ans = left = 0
        for b in s:
            cnt[b] -= 1
            if cnt[b] == 0:
                # 窗口内 b 的出现次数和 t 一样
                less -= 1
            while less == 0:  # 窗口符合要求
                if cnt[s[left]] == 0:
                    # s[left] 移出窗口之前,检查出现次数,
                    # 如果窗口内 s[left] 的出现次数和 t 一样,
                    # 那么 s[left] 移出窗口后,窗口内 s[left] 的出现次数比 t 的少
                    less += 1
                cnt[s[left]] += 1
                left += 1
            ans += left
        return ans

golang 解法, 执行用时: 3 ms, 内存消耗: 5.3 MB, 提交时间: 2024-10-13 23:35:38

func validSubstringCount(s, t string) (ans int64) {
	if len(s) < len(t) {
		return 0
	}
	cnt := [26]int{} // t 的字母出现次数与 s 的字母出现次数之差
	for _, b := range t {
		cnt[b-'a']++
	}
	less := 0 // 统计窗口内有多少个字母的出现次数比 t 的少
	for _, c := range cnt {
		if c > 0 {
			less++
		}
	}

	left := 0
	for _, b := range s {
		cnt[b-'a']--
		if cnt[b-'a'] == 0 {
			// 窗口内 b 的出现次数和 t 一样
			less--
		}
		for less == 0 { // 窗口符合要求
			if cnt[s[left]-'a'] == 0 {
                // s[left] 移出窗口之前,检查出现次数,
                // 如果窗口内 s[left] 的出现次数和 t 一样,
                // 那么 s[left] 移出窗口后,窗口内 s[left] 的出现次数比 t 的少
				less++
			}
			cnt[s[left]-'a']++
			left++
		}
		ans += int64(left)
	}
	return
}

cpp 解法, 执行用时: 18 ms, 内存消耗: 13.6 MB, 提交时间: 2024-10-13 23:35:13

class Solution {
public:
    long long validSubstringCount(string s, string t) {
        if (s.length() < t.length()) {
            return 0;
        }
        int cnt[26]{}; // t 的字母出现次数与 s 的字母出现次数之差
        for (char b : t) {
            cnt[b - 'a']++;
        }
        int less = 0; // 统计窗口内有多少个字母的出现次数比 t 的少
        for (int c : cnt) {
            if (c > 0) {
                less++;
            }
        }

        long long ans = 0;
        int left = 0;
        for (char b : s) {
            cnt[b - 'a']--;
            if (cnt[b - 'a'] == 0) {
                // b 移入窗口后,窗口内 b 的出现次数和 t 一样
                less--;
            }
            while (less == 0) { // 窗口符合要求
                char out_char = s[left++]; // 准备移出窗口的字母
                if (cnt[out_char - 'a'] == 0) {
                    // out_char 移出窗口之前,检查出现次数,
                    // 如果窗口内 out_char 的出现次数和 t 一样,
                    // 那么 out_char 移出窗口后,窗口内 out_char 的出现次数比 t 的少
                    less++;
                }
                cnt[out_char - 'a']++;
            }
            ans += left;
        }
        return ans;
    }
};

java 解法, 执行用时: 5 ms, 内存消耗: 44.1 MB, 提交时间: 2024-10-13 23:34:58

class Solution {
    public long validSubstringCount(String S, String T) {
        if (S.length() < T.length()) {
            return 0;
        }

        char[] s = S.toCharArray();
        char[] t = T.toCharArray();
        int[] cnt = new int[26]; // t 的字母出现次数与 s 的字母出现次数之差
        for (char b : t) {
            cnt[b - 'a']++;
        }
        int less = 0; // 统计窗口内有多少个字母的出现次数比 t 的少
        for (int c : cnt) {
            if (c > 0) {
                less++;
            }
        }

        long ans = 0;
        int left = 0;
        for (char b : s) {
            cnt[b - 'a']--;
            if (cnt[b - 'a'] == 0) {
                // b 移入窗口后,窗口内 b 的出现次数和 t 一样
                less--;
            }
            while (less == 0) { // 窗口符合要求
                char outChar = s[left++]; // 准备移出窗口的字母
                if (cnt[outChar - 'a'] == 0) {
                    // outChar 移出窗口之前检查出现次数,
                    // 如果窗口内 outChar 的出现次数和 t 一样,
                    // 那么 outChar 移出窗口后,窗口内 outChar 的出现次数比 t 的少
                    less++;
                }
                cnt[outChar - 'a']++;
            }
            ans += left;
        }
        return ans;
    }
}

上一题