线段树+模拟
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
char str[1000005];
int T[26<<2];
int M;
inline void build()
{
for(M=1;M<28;M<<=1);
memset(T,0,sizeof(int)*(M+M));
}
void pushup(int x)
{
T[x>>=1]=0;
if(T[x<<1])T[x]++;
if(T[x<<1|1])T[x]++;
for(x>>=1;x;x>>=1)
T[x] = T[x<<1] + T[x<<1|1];
}
void add(int x)
{
T[x+=M]++;
if(T[x]==1)
pushup(x);
}
void sub(int x)
{
T[x+=M]--;
if(T[x]==0)
pushup(x);
}
#define query() T[1]
int main()
{
int n,k;
scanf("%d",&n);
while(n--)
{
long long ans = 0;
scanf("%s%d",str+1,&k);
int len = strlen(str+1);
int pa = 1;
int pb = 1;
//[pa,pb]
build();
for(;pb<=len;pb++)
{
add(str[pb]-'a'+1);
if(query() == k)
{
while(query()==k)
sub(str[pa++]-'a'+1);
add(str[--pa]-'a'+1);
ans += pa;
}
if(query()>k)
{
do{
sub(str[pa++]-'a'+1);
}while(query()>k);
while(query()==k)
sub(str[pa++]-'a'+1);
add(str[--pa]-'a'+1);
ans +=pa;
}
}
printf("%I64d\n",ans);
}
return 0;
}