力扣题解(统计满足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 小时前
2024-11-16 串的定义和基本操作
数据结构
励志成为嵌入式工程师1 小时前
数据结构(单向链表——c语言实现)
c语言·数据结构·链表
阿七想学习1 小时前
数据结构《栈和队列》
java·开发语言·数据结构
Fms_Sa2 小时前
假设一棵平衡二叉树的每个结点都表明了平衡因子b,试设计一个算法,求平衡二叉树的高度。
c语言·数据结构·算法
yangmc042 小时前
区间和 离散化 模板题
c语言·数据结构·c++·算法·矩阵·objective-c
钰爱&2 小时前
【C】链表的创建、打印、插入、删除等
c语言·开发语言·数据结构·笔记·学习·链表
三小尛3 小时前
归并排序(C语言)
c语言·数据结构·算法
小吉在努力敲代码中4 小时前
c++实现B树(下)
开发语言·数据结构·c++·b树·算法
♡喜欢做梦4 小时前
【数据结构】栈和队列详解!!!--Java
java·开发语言·数据结构·链表