力扣刷题——3306. 元音辅音字符串计数 II

好久没搞刷题了,搞副业搞晕了。。。
看到题的第一感觉是滑动窗口,直接开写。

class Solution
{
public:
    int countOfSubstrings(string word, int k)
    {
        vector<int> cnt(26, 0);
        int left = 0, right = 0;
        int res = 0;
        while (right < word.size())
        {
            cnt[word[right] - 'a']++;

            int tem = check(cnt);
            if (tem == -1)
            {
                right++;
                continue;
            }

            if (right - left + 1 - tem > k)
            {
                cnt[word[left] - 'a']--;
                cnt[word[right] - 'a']--;
                left++;
                continue;
            }

            if (right - left + 1 - tem == k)
            {
                res++;
            }
            right++;
        }

        cnt[word[left] - 'a']--;
        left++;
        right--;
        while (true)
        {
            int tem = check(cnt);
            if (tem == -1)
                break;
            if (right - left + 1 - tem < k)
                break;
            if (right - left + 1 - tem == k)
            {
                res++;
            }
            cnt[word[left] - 'a']--;
            left++;
        }

        return res;
    }
    
    int check(vector<int> &cnt)
    {
        if (cnt['a' - 'a'] == 0 || cnt['e' - 'a'] == 0 || cnt['i' - 'a'] == 0 || cnt['o' - 'a'] == 0 || cnt['u' - 'a'] == 0)
            return -1;
        int tem = cnt['a' - 'a'] + cnt['e' - 'a'] + cnt['i' - 'a'] + cnt['o' - 'a'] + cnt['u' - 'a'];
        return tem;
    }
};

调整了好几遍,结果写了一坨。。。关键还是没有过。。。
重新看了一遍上边的代码,感觉槽点太多了,本来是个左闭右开的滑动窗口,结果写的乱七八糟。回到问题上,在对用例word = "ieiaoud", k = 0分析了一下之后,发现只用一个滑动窗口难以解决这个问题,看了下题解,用两个滑动窗口就能够很好的解决。
核心思路再写一个函数sub(k),能够输出满足子串中非元音字母数>=k的子串数量,这样最终答案就是用sub(k) - sub(k + 1),实现如下:

class Solution
{
public:
    long long countOfSubstrings(string word, int k)
    {
        return sub(word, k) - sub(word, k + 1);
    }

    long long sub(string &word, int k)
    {
        int n = word.size();
        int left = 0, right = 0;
        vector<int> cnt(26, 0);
        long long res = 0;
        while (left < n)
        {
            while (right < n && (right - left - check(cnt) < k || check(cnt) == -1))
            {
                cnt[word[right] - 'a']++;
                right++;
            }

            if ((right - left - check(cnt)) >= k && check(cnt) != -1)
            {
                // 以[left...right]为前缀的子串都满足
                res += n - right + 1;
            }

            cnt[word[left] - 'a']--;
            left++;
        }
        return res;
    }

    int check(vector<int> &cnt)
    {
        if (cnt['a' - 'a'] == 0 || cnt['e' - 'a'] == 0 || cnt['i' - 'a'] == 0 || cnt['o' - 'a'] == 0 || cnt['u' - 'a'] == 0)
            return -1;
        int tem = cnt['a' - 'a'] + cnt['e' - 'a'] + cnt['i' - 'a'] + cnt['o' - 'a'] + cnt['u' - 'a'];
        return tem;
    }
};
posted @ 2025-03-13 16:47  SuzumiyaYui  阅读(14)  评论(0)    收藏  举报