数字串

题目链接:nowcoder 218049

到主站看:https://blog.csdn.net/weixin_43346722/article/details/116779763

题目大意

给你一个由数字字符组成的字符串,和两个数。
问你你能在字符串中截出一个子串,它形成的数字在两个数之间(包括这两个数)。
提出的数可以有前导 0。

思路

首先我们考虑没有前导 0 怎么做。

那就直接枚举每个位数符合的子串,然后匹配。
但是有前导 0,可能就会有一个看起来位数不符合,但是把前导 0 去掉之后又符合了的情况。

那就考虑把前导 0 去掉,然后得出如果匹配就不是加一而是加前导 0 的个数+1。(+1 是因为可以一个前导零都不要)

代码

#include<cstdio>
#include<cstring>

using namespace std;

char L[500001], R[500001], s[500001];
int n, Ln, Rn, ans;

bool check(int l, int r) {//判断是否在两个数之间
    if (r - l + 1 < Ln) return 0;//看长度就知道不符合
    if (r - l + 1 > Rn) return 0;
    if (r - l + 1 == Ln) {//位数相同才要比较,不然直接可以确定可以(下同)
        for (int i = l; i <= r; i++) {
            if (s[i] > L[i - l + 1]) break;
            if (s[i] < L[i - l + 1]) return 0;
        }
    }
    if (r - l + 1 == Rn) {
        for (int i = l; i <= r; i++) {
            if (s[i] < R[i - l + 1]) break;
            if (s[i] > R[i - l + 1]) return 0;
        }
    }
    return 1;
}

int main() {
    scanf("%s %s\n%s", L + 1, R + 1, s + 1);
    Ln = strlen(L + 1);
    Rn = strlen(R + 1);
    n = strlen(s + 1);

    int qdl = 0;
    for (int i = 1; i <= n; i++) {
        if (s[i] == '0') {//处理前导 0
            qdl++;
            continue;
        }
        for (int j = Ln; j <= Rn && j + i - 1 <= n; j++)
            ans += (qdl + 1) * check(i, i + j - 1);//前导 0 选多少个都可以,所以要乘上个数加一
        qdl = 0;//清空前导零个数
    }

    printf("%lld", ans);

    return 0;
}