codeforces1311C. Perform the Combo

题目连接: 老师永远不知道在上网课的学生都在干嘛

给出一个字符串,再给出m个子串,求子串和原串个字母出现的次数


这题不是很难,最难的是好久不写把输出函数给忘了
最朴素的算法就是把每个子串都走一遍累加,但是时间和空间复杂都太高,所以就想,能不能统计每个位置出现的次数。

每个子串结束之前必然要计数一次,所以记录每个子串结束的位置,倒序遍历原串,若当前位置有子串结束,那么之前的位置都要计数一次,所以出现次数+1.
要注意的是这里不只有子串,还有原串,因此原串的最后一个位置初始值为1

#pragma GCC diagnostic error "-std=c++11"
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define Pair pair<int,int>
#define re return

#define getLen(name,index) name[index].size()
#define mem(a,b) memset(a,b,sizeof(a))
#define Make(a,b) make_pair(a,b)
#define Push(num) push_back(num)
#define rep(index,star,finish) for(register int index=star;index<finish;index++)
#define drep(index,finish,star) for(register int index=finish;index>=star;index--)
using namespace std;

template<class T> void _deb(const char *name,T val){
    cout<<name<<val<<endl;
}

const int maxn=2e5+5;

int T;
int n,m;
char store[maxn];  %原串
int mistake[maxn];  %错误位置
int times[maxn];  %每个位置的出现次数
int statistics[26];  %每个字母出现的总次数
int main(){
    scanf("%d",&T);
    while(T--){
        mem(statistics,0);
        mem(times,0);

        scanf("%d%d",&n,&m);
        scanf("%s", store+1);
        rep(i,0,m){
            scanf("%d",&mistake[i]);
        }

        sort(mistake,mistake+m);
        times[n]=1;
        drep(i,m-1,0){
            times[mistake[i]]+=1;
        }
        drep(i,n,1){
            int pos = store[i]-'a';
            times[i] += times[i+1];
            statistics[pos] += times[i];
        }

        rep(i,0,26){
            printf("%d ",statistics[i]);
        }
        printf("\n");
    }
    re 0;
}

猜你喜欢

转载自blog.csdn.net/white_156/article/details/104493960
今日推荐