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

11 阅读1分钟

给你两个字符串 word1word2

如果一个字符串 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

解释:

  • 1 <= word1.length <= 105

  • 1 <= word2.length <= 104

  • word1word2 都只包含小写英文字母。

思路:

可以将一个字符串重新排列后使字符串 word 2 ​ 是重排字符串的前缀

等价于原始字符串覆盖字符串 word2 ​ 的所有字符

因此问题等价于计算字符串 word1 ​ 的覆盖字符串 word2 ​ 的所有字符的子字符串数目

题解:

class Solution {    public long validSubstringCount(String word1, String word2) {       // 当word1小于word2时,直接返回0        if (word1.length() < word2.length()){            return 0L;        }        // 滑动窗口        // 初始化结果        long result = 0;        // 存储字符串word2中每个字符出现的次数        Map<Character, Integer> word2Map = new HashMap<>();        for (int i = 0; i < word2.length(); i++) {            word2Map.put(word2.charAt(i), word2Map.getOrDefault(word2.charAt(i), 0) + 1);        }        // 记录滑动窗口中每个字符出现的次数        Map<Character, Integer> windowMap = new HashMap<>();        // 记录匹配字符的数量        Integer matchCount = 0;        // 左指针        Integer left = 0;        // 右指针        Integer right =  0;        // 滑动右指针        while (right < word1.length()){            char rightChar  = word1.charAt(right);            windowMap.put(rightChar, windowMap.getOrDefault(rightChar, 0) + 1);            // 判断字符出现次数是否匹配            if (word2Map.containsKey(rightChar) && windowMap.get(rightChar).equals(word2Map.get(rightChar))){                // 如果该字符在滑动窗口和word2中都出现过,且出现次数相同,则匹配数量加1                matchCount++;            }            // 当每个字符出现次数完全一致,则滑动左指针            while (matchCount == word2Map.size()){                // 从right开始,后续字符串全部符合要求                result += word1.length() - right;                // 缩小左端,移除该字符                char leftChar = word1.charAt(left);                if (windowMap.get(leftChar) > 0){                    windowMap.put(leftChar, windowMap.get(leftChar) - 1);                }                // 判断频次是否匹配,如果不匹配则匹配数量减1                if (word2Map.containsKey(leftChar) && windowMap.get(leftChar) < word2Map.get(leftChar)){                    matchCount--;                }                // 滑动左指针                left++;            }            // 滑动右指针            right++;        }        return result;    }}