遊遊的好串(攜程24秋招研發崗第一批)

athenanevergiveup發表於2024-04-17

題面

遊遊的好串
遊遊有一個只包含'0'和'1'的字串,他想知道這個字串有多少個好子串?

一個字串如果是"好串",那麼該字串的所有字首,'0'的數量嚴格大於'1'的數量。

輸入

輸入一個只包含'0'和'1'的字串,長度不超過100000。

輸出

輸出一個整數,代表答案。

示例

輸入例子:

100

輸出例子:

3

例子說明:
子區間 [2, 2], [2, 3], [3, 3] 組成的子串都是一個好串。

輸入例子:

10010

輸出例子:

6

例子說明:
子區間 [2, 2], [3, 3], [2, 3], [2, 4], [2, 5], [5, 5] 組成的子串是一個好串。

核心思想

滑動視窗
首先要明確的一點時視窗滑動的過程本身就是字首
那麼視窗兩端 l,r 表示 從 l 開始,以 r 結尾的所有子串滿足要求的有多少個
這一步操作就是選擇了子串 [l,r] [l+1,r]....[r,r]
以 10010 為例

當視窗來到 l = 2, r = 4 時(下標從1開始)視窗串為 001
我們執行 res += (r - l + 1); 這一計算的意義是什麼?
我們認為 001, 01, 1 這樣的字串都滿足要求 但事實上 01, 1 是需要剔除的
分析後可以發現是因為有1的存在
分為兩種情況

  1. 以 1 開頭的子串, 數量為視窗內 1 的個數
  2. 第二種就是上面例子中 01 這樣的 前面0的個數太少 這樣的有多少個?同樣是 1 的個數

我們換一個例子 0010101,視窗會來到 l = 1, r = 7, cnt1 = 3(視窗內1的個數)
010101, 10101
0101, 101
01, 1
這些都是不滿足的 也就是1的個數乘2

程式碼

import java.util.*;

class Main {
    static final int MAXN = (int) (1e5 + 10);
    static char[] chs = new char[MAXN];
    static long res = 0;
    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        String s = scanner.next();
        int n = s.length();
        for(int i = 1; i <= n; i++){
            chs[i] = s.charAt(i - 1);
        }
        int cnt1 = 0, cnt0 = 0;
        for(int l = 1, r = 1; r <= n; r++){
            if(chs[r] == '0')
                cnt0++;
            else{
                cnt1++;
            }

            while(cnt1 >= cnt0 && l <= r){
                if(chs[l] == '0')
                    cnt0--;
                else
                    cnt1--;
                l++;
            }
            res += (r - l + 1);
            res -= 2L * cnt1;
        }
        System.out.println(res);
    }
}

相關文章