方法一:打表
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int mis[maxn];
int main()
{
int zi[200];
int z1[27][maxn];
int t,x,y;
char a[maxn];
scanf("%d",&t);
while(t--)
{
for(int i=0;i<=30;i++) zi[i]=0;
for(int i=1;i<=26;i++) z1[i][0]=0;
scanf("%d%d",&x,&y);
scanf("%s",a);
for(int i=1;i<=y;i++)
{
scanf("%d",&mis[i]);
}
mis[y+1]=x;
y++;
int top=0;
z1[a[0]-'a'+1][0]++;
for(int i=1;i<x;i++)
{
for(int j=1;j<=26;j++)
{
z1[j][i]=z1[j][i-1];
}
z1[a[i]-'a'+1][i]++;
}
for(int j=1;j<=y;j++)
{
for(int i=1;i<=26;i++)
{
zi[i]+=z1[i][mis[j]-1];
}
}
for(int i=1;i<=26;i++)
{
if(i==26)
printf("%d\n",zi[i]);
else printf("%d ",zi[i]);
}
}
return 0;
}
方法二:倒序遍历求和(别忘了子串)
```cpp
#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;cin>>t;
while(t--)
{
int n,m;cin>>n>>m;
string s;cin>>s;
int a[m];
vector<int> v(n+1,0);
for(int i=0;i<m;i++)
{
cin>>a[i];
v[a[i]]++;//出现错误的位数存起来
}
for(int i=n-1;i>=0;i--)
v[i] += v[i+1] ;//越靠前的加的越多,仔细想想是这个理
int arr[26]={0};
for(int i=1;i<=n;i++)
arr[s[i-1]-97] += v[i] + 1;//+1是因为本来就有一遍
for(int i=0;i<26;i++)
cout<<arr[i]<<" ";
cout<<endl;
}
return 0;
}