这里我使用的是动态规划的方法,先对一串字符串计算它的前缀和。
核心代码
for(int i=0;i<len;i++) {
if (i>0)
for(int q=0;q<26;q++)
{
b[i][q]=b[i-1][q];
}
b[i][a[i]-'a']++;
}
到字符串末尾时,每个位置前面每个字母出现了多少次都记录其中。
开始我TimeOut的原因是使用memset频繁初始化了b这个二维数组,造成了时间上的浪费,日后这种问题,只需要初始化二维数组最开始的那一串。例如本题初始化
for(int i=0;i<26;i++)
b[0][i]=0;
完整代码
#include <cstdio>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=2*1e5+50000;
char a[maxn];
int vis[30];
int b[maxn][28];
int main(void)
{
int t;
while(scanf("%d",&t)!=EOF)
while(t--)
{
memset(vis,0,sizeof(vis));
for(int i=0;i<26;i++)
b[0][i]=0;
int n,m,k;
scanf("%d%d",&n,&m);
scanf("%s",a);
int len=strlen(a);
for(int i=0;i<len;i++)
{
if (i>0)
for(int q=0;q<26;q++)
{
b[i][q]=b[i-1][q];
}
b[i][a[i]-'a']++;
}
for(int i=1;i<=m;i++)
{
scanf("%d",&k);
for(int j=0;j<26;j++)
{
vis[j]+=b[k-1][j];
}
}
for(int j=0;j<26;j++)
{
vis[j]+=b[len-1][j];
}
for(int i=0;i<26;i++)
{
printf("%d",vis[i]);
if (i!=25) printf(" ");
else printf("\n");
}
}
return 0;
}