力扣题解(统计满足k约束的子字符串数目)

3261. 统计满足 K 约束的子字符串数量 II

已解答

困难

相关标签

相关企业

提示

给你一个 二进制 字符串 s 和一个整数 k

另给你一个二维整数数组 queries ,其中 queries[i] = [li, ri]

如果一个 二进制字符串 满足以下任一条件,则认为该字符串满足 k 约束

  • 字符串中 0 的数量最多为 k
  • 字符串中 1 的数量最多为 k

返回一个整数数组 answer ,其中 answer[i] 表示 s[li..ri] 中满足 k 约束 的 子字符串 的数量。

思路:

首先,对于一个给定的l到r区间,可以分成两部分,即l到k和k到r,分界处使得l到k中任意子串都满足k约束,k到r可能满足可能不满足k约束,这样,l到k这一段区间的子字符串的个数就是k-l+1,k-l,k-l-1.......1,总共(k-l+1)*(k-1+2)/2;就是单纯等差数列求和。对于k到r这个区间,则可以考虑用前缀和数组来求解,规定前缀和数组是从0到当前位置的所有子字符串的数目,这样两端点相减就是k到r这一块的子字符串的个数。那么,根据分析,需要求的就是每一个端点的前缀和数组和每个点满足右侧某段点rr到当前点的区间内的所有点都符合子字符串的最大rr。

对于求解右端点,可以利用双指针的算法,思路是找每个右端点是哪个左端点的的符合条件的右端点,这样,对于一个右端点更大的位置,其对应的左端点一定是更大的,两指针都是只能向右侧移动,具体求解办法就是遍历字符串,对于下标i,如果当前j下标到i下标符合k约束(代码中是找到最右侧不符合的那个那个i),则r[j]=i,否则j++一直到符合k约束。对于求的前缀和,则可以利用j++直到符合k约束这一步,因为此时的j就是对于i这个位置,以i为右端点的最长符合k约束的子字符串,因此对于以i为右端点,长度在j到i之间的子串,一定都符合k约束,因此i这个点作为右端点所能提供的子字符串的个数就是i-j+1,这样就可以更新前缀和了。

对于每个查找区间l到r,首先找到l的右端点,然后和r比较,如果右端点小于r,则分成两个部分l到右端点和右端点到r分别求子字符串的个数,否则则只需要求l到r的子字符串的个数(此时表示l到r内任意长度子字符串都符合k约束)。

本题存在很多边界情况,且数组表示的意义很多是不符合条件的第一个边界,因此某些地方求长度实际上是需要主要要减小的。另外,还需要注意前缀和的下标。

复制代码
class Solution {
public:
   typedef long long LL;
    vector<long long> countKConstraintSubstrings(string s, int k, vector<vector<int>>& queries) {
        int n=s.size();
        vector<LL>sum(n+1,0);
        vector<int>count(2,0);
        vector<int>right(n,n);
        for(int i=0,j=0;i<n;i++)
        {   
            count[s[i]-'0']++;
            while(count[0]>k&&count[1]>k)
            {
               count[s[j]-'0']--;
               right[j]=i;
               j++;
            }
            sum[i+1]=(LL)sum[i]+i-j+1;
        }
        vector<LL>res;
        for(int i=0;i<queries.size();i++)
        {
             int l=queries[i][0],r=queries[i][1];
             int j=min(right[l],r+1);
             LL t1=(LL)(j-l)*(j-l+1)/2;
             LL t2=sum[r+1]-sum[j];
             res.push_back(t1+t2);
        }
        return res;

    }
};
相关推荐
偷偷的卷1 小时前
【算法笔记 day three】滑动窗口(其他类型)
数据结构·笔记·python·学习·算法·leetcode
凤年徐2 小时前
【数据结构】时间复杂度和空间复杂度
c语言·数据结构·c++·笔记·算法
kualcal2 小时前
代码随想录17|二叉树的层序遍历|翻转二叉树|对称二叉树
数据结构·算法
钮钴禄·爱因斯晨2 小时前
C语言 | 函数核心机制深度解构:从底层架构到工程化实践
c语言·开发语言·数据结构
努力写代码的熊大3 小时前
链式二叉树数据结构(递归)
数据结构
yi.Ist3 小时前
数据结构 —— 键值对 map
数据结构·算法
爱学习的小邓同学3 小时前
数据结构 --- 队列
c语言·数据结构
s153353 小时前
数据结构-顺序表-猜数字
数据结构·算法·leetcode
闻缺陷则喜何志丹3 小时前
【前缀和 BFS 并集查找】P3127 [USACO15OPEN] Trapped in the Haybales G|省选-
数据结构·c++·前缀和·宽度优先·洛谷·并集查找
lifallen9 小时前
Paimon LSM Tree Compaction 策略
java·大数据·数据结构·数据库·算法·lsm-tree