解题思路:

1.直接暴力遍历出c1,c2的位置数组,以及c1,c2的数量。

2.遍历c1,c2数组,用双循环,每一个c1第一次匹配成功c2后边的c2是一定可以匹配这个c1的,时记录该c2的位置,并且下一个c1直接从该位置开始匹配c2.

参考代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long          //这里注意一定要开long long因为字符串长在5*10^5级别!!
signed main()
{
    int k;
    int num=0;
    char str[500001];          //预留一位存放\0
    char start,end;            //也就是c1 c2
    scanf("%lld %s %c %c",&k,&str,&start,&end);
    int len=0;                 //求字符串长
    while(str[len]!='\0')
    {
        len++;
    }
    int startl[len],endl[len];  //存放c1和c2
    int l=0;                    //定义c1和c2的个数
    int j=0;
    for(int i=0;i<len;i++)      //填充c1 c2数组
    {
        if(str[i]==start)
        {
            startl[j]=i;
            j++;
        }
        if(str[i]==end)
        {
            endl[l]=i;
            l++;
        }
    }
    int oo[len]={0};            //oo数组记录离当前c1最近的c2,即oo[0],下一个c1匹配c2即可直接从oo[0]开始遍历c2
    for(int i=0;i<j;i++)
    {
        int oi=0;
        for(int i2=oo[0];i2<l;i2++)
        {
            if(endl[i2]-startl[i]+1>=k)   //如果子串长度大于等于k即为匹配成功
            {
                oo[oi]=i2;
                oi++;
                
                num+=l-i2;                //如果该c2匹配成功则说明后面的c2肯定是子串长大于k的,也一定能匹配上
                                          //所以就不用遍历后边的c2,直接加上去并且break以降低时间复杂度。
                break;
            }
        }
    }
    printf("%lld",num);                   //注意输出格式为lld;
}


点赞(0)
 

0.0分

0 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 0 条评论

暂无评论