文字列の 0 番目から i 番目までに各文字がどれくらいあるかを前もって数えておく。
#include <algorithm>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <sstream>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#define REP(i, n) for(int i=0; i<(int)n; ++i)
#define FOR(i, c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(),(c).end()
#define each(i, c) FOR(i, c)
#define VAR(a) cout << #a << " : " << a << endl;
typedef long long int lli;
using namespace std;
int main(int argc, char *argv[])
{
int tc;
cin >> tc;
const int N = 10000 + 1;
const int C = 'z' + 1;
int cnt[C][N];
while (tc--) {
fill(&cnt[0][0], &cnt[C - 1][N], 0);
int k;
cin >> k;
int cut[k];
for (int i = 0; i < (int)k; ++i) {
cin >> cut[i];
}
string s;
cin >> s;
for (int i = 0; i < (int)s.size(); ++i) {
++cnt[s[i]][i + 1];
}
for (int c = 0; c < (int)C; ++c) {
for (int i = 1; i < (int)N; ++i) {
cnt[c][i] += cnt[c][i - 1];
}
}
vector<int> v;
v.push_back(0);
v.push_back(s.size());
int sum = 0;
for (int i = 0; i < (int)k; ++i) {
int idx = distance(v.begin(), lower_bound(v.begin(), v.end(), cut[i]));
int begin = v[idx - 1];
int end = v[idx];
int cost = 0;
for (int c = 'a'; c <= 'z'; ++c) {
int a = cnt[c][cut[i]] - cnt[c][begin];
int b = cnt[c][end] - cnt[c][cut[i]];
if (a && b) ;
else if (a || b) ++cost;
}
v.push_back(cut[i]);
sort(v.begin(), v.end());
sum += cost;
}
cout << sum << endl;
}
return 0;
}