第十四届蓝桥杯省赛C++B组G题【子串简写】题解(AC)






题目大意

给定字符串 s s s,字符 a , b a, b a,b,问字符串 s s s 中有多少个 a a a 开头 b b b 结尾的子串。

解题思路

20pts

使用二重循环枚举左端点和右端点,判断是否为 a a a 开头 b b b 结尾的字符串,是则答案加一。

100pts

数据范围较大,我们需要将时间复杂度控制在 O ( n log ⁡ n ) O(n\log n) O(nlogn) 以内。

法一

我们需要找到所有 a a a 开头 b b b 结尾的字符串,那么我们可以对于每个字符 b b b,去看 b b b 的左侧有几个 a a a,那么这些 a ... b a\dots b a...b 就是合法的字符串。统计某个位置的左侧有几个字符 a a a,我们可以使用前缀和算法进行维护。

法二

我们可以去遍历整个字符串,对于每个 a a a 字符的右侧有几个字符 b b b,那么这些 a ... b a \dots b a...b 都是合法的字符串。统计某个位置之后字符 b b b 的个数,可以使用后缀和算法进行维护。

cpp 复制代码
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N = 5e5 + 10;

int n, m;
string str;
char a, b;
int s[N];

int main()
{
    cin >> m >> str >> a >> b;
    n = str.size();
    str = ' ' + str;
    
    for (int i = n; i; -- i )
        s[i] = s[i + 1] + (str[i] == b);
    
    LL res = 0;
    for (int i = 1; i + m - 1 <= n; ++ i )
        if (str[i] == a)
            res += s[i + m - 1];
    
    cout << res << endl;
    
    return 0;
}

【在线测评】

相关推荐
小小编程路1 小时前
C++ 多线程与并发
java·jvm·c++
程序leo源2 小时前
Qt窗口详解
开发语言·数据库·c++·qt·青少年编程·c#
zh_xuan3 小时前
解决VS Code 控制台中文乱码
c++·vscode·乱码
郭涤生3 小时前
飞凌 RK3588 开发板同显 / 异显模式切换
c++·rk3588
计算机安禾3 小时前
【c++面向对象编程】第38篇:设计原则(二):里氏替换、接口隔离与依赖倒置
开发语言·c++
code_whiter4 小时前
C++1进阶(继承)
开发语言·c++
智者知已应修善业4 小时前
【51单片机LED闪烁10次数码管显示0-9】2023-12-14
c++·经验分享·笔记·算法·51单片机
智者知已应修善业4 小时前
【51单片机2按键控制1个敞亮LED灯闪烁和熄灭】2023-11-3
c++·经验分享·笔记·算法·51单片机
咩咦5 小时前
C++学习笔记20:日期类比较运算符重载
c++·学习笔记·类和对象·运算符重载·比较运算符·日期类
凌波粒5 小时前
LeetCode--404.左叶子之和(二叉树)
算法·leetcode·职场和发展