练习codeforces1272C. Yet Another Broken Keyboard

题目如下
time limit per test2 seconds
memory limit per test256 megabytes
Recently, Norge found a string 𝑠=𝑠1𝑠2…𝑠𝑛 consisting of 𝑛 lowercase Latin letters. As an exercise to improve his typing speed, he decided to type all substrings of the string 𝑠. Yes, all 𝑛(𝑛+1)2 of them!

A substring of 𝑠 is a non-empty string 𝑥=𝑠[𝑎…𝑏]=𝑠𝑎𝑠𝑎+1…𝑠𝑏 (1≤𝑎≤𝑏≤𝑛). For example, "auto" and "ton" are substrings of "automaton".

Shortly after the start of the exercise, Norge realized that his keyboard was broken, namely, he could use only 𝑘 Latin letters 𝑐1,𝑐2,…,𝑐𝑘 out of 26.

After that, Norge became interested in how many substrings of the string 𝑠 he could still type using his broken keyboard. Help him to find this number.

Input
The first line contains two space-separated integers 𝑛 and 𝑘 (1≤𝑛≤2⋅105, 1≤𝑘≤26) — the length of the string 𝑠 and the number of Latin letters still available on the keyboard.

The second line contains the string 𝑠 consisting of exactly 𝑛 lowercase Latin letters.

The third line contains 𝑘 space-separated distinct lowercase Latin letters 𝑐1,𝑐2,…,𝑐𝑘 — the letters still available on the keyboard.

Output
Print a single number — the number of substrings of 𝑠 that can be typed using only available letters 𝑐1,𝑐2,…,𝑐𝑘.

题目大意
在已有的字符串基础上,现只有k个字符能够顺利打出,问此时除去不能够打出的字符外的子字符串数量(不能跳过不能打出的字符)

题目分析
把能够打出的字符转换为十进制的数字形式存储在veceor数组中,在统计最大子字符串的数量时匹配可用的字符来确认字符

点击查看代码
for(int i = 0; i < k; i++){
        char ch;
        scanf(" %c",&ch);
        ss.push_back(ch - 'a'); //把可用字符存入数组
    }
    long long len = 0,total = 0;
    for(int i = 0; i < n; i++){
        int c = s[i] - 'a';
        if(find(ss.begin(),ss.end(),c) != ss.end()){
            len++;
        }else{
            total += (len + 1) * len / 2 ; //对每个连续字符串的子字符串进行计数
            len = 0; //当前字符不可用,连续字符串归零
        }
    }
根据子字符串的计数规则能够得出,每个连续的子字符串所含有的子字符串数量为(len + 1) * len / 2; 注意,最后的连续子字符串并没包含子在total里,所以需要再循环外加上最后的连续子字符串的子字符串数量

完整代码

点击查看代码
#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;

int main(){
    int n,k;
    scanf("%d%d",&n,&k);
    char s[200005];
    scanf("%s",s);
    vector<int> ss;
    for(int i = 0; i < k; i++){
        char ch;
        scanf(" %c",&ch);
        ss.push_back(ch - 'a'); //把可用字符存入数组
    }
    long long len = 0,total = 0;
    for(int i = 0; i < n; i++){
        int c = s[i] - 'a';
        if(find(ss.begin(),ss.end(),c) != ss.end()){
            len++;
        }else{
            total += (len + 1) * len / 2 ; //对每个连续字符串的子字符串进行计数
            len = 0; //当前字符不可用,连续字符串归零
        }
    }
    total += (len + 1) * len / 2;
    printf("%lld",total);
    return 0;
}
posted @ 2025-07-05 20:29  sirro1uta  阅读(11)  评论(0)    收藏  举报