因为每个串的不同回文子串数目是 O(n) 的,考虑求出不同的子串及其数目,显然回文树可以搞,构建完回文树之后按照最长回文后缀边产生的拓扑序下推标记,查询时直接dfs整棵树求出每个串的value后排序即可。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define clr(a) memset(a,0,sizeof(a))
typedef long long ll;
const ll md=777777777;
char cz[100010];int n,m,tn,nx[100010][26],px[100010],le[100010],dg[100010],ar[26];ll fr[100010],sm[100010],fg[100010];
struct bi{ll a,b;}xr[100010];
bool bimp(const bi&a,const bi&b){return a.a<b.a;};
void pshd(int v){
if(px[v]>1)fg[px[v]]+=fg[v],sm[px[v]]+=fg[v];
fg[v]=0;
};
void _cl(){
int i,j,t,tn,lst;clr(dg),clr(nx[0]),clr(nx[1]),px[1]=0,le[0]=-1,le[1]=0;
for(tn=i=1,lst=0;i<=n;++i){
for(t=cz[i]-'a',j=lst;cz[i]!=cz[i-le[j]-1];j=px[j]);
if(nx[j][t]){lst=nx[j][t];sm[lst]++,fg[lst]++;}
else{
lst=++tn;clr(nx[tn]),le[tn]=le[j]+2,nx[j][t]=tn,sm[tn]=fg[tn]=1;
for(j=px[j];cz[i]!=cz[i-le[j]-1];j=px[j]);
px[tn]=le[tn]>1?nx[j][t]:1;if(px[tn]>1)dg[px[tn]]++;
}
}
queue<int>qe;for(i=2;i<=tn;++i)if(!dg[i])qe.push(i);
for(;!qe.empty();){
t=qe.front();qe.pop();pshd(t),dg[px[t]]--;
if(px[t]>1&&!dg[px[t]])qe.push(px[t]);
}
};
void _clfr(){
int i;for(fr[0]=1,i=1;i<=100000;++i)
fr[i]=fr[i-1]*26%md;
};
void dfs(int v,ll x,int d){
if(d){xr[tn].a=x,xr[tn].b=sm[v];++tn;}
int i;for(i=0;i<26;++i)if(nx[v][i]){
dfs(nx[v][i],(x+fr[d]*ar[i])%md,d+1);
}
};
void cl(){
int i;ll j,k;scanf("%d %d",&n,&m);scanf("%s",cz+1);
for(_cl();m;m--){
for(scanf("%I64d",&k),i=0;i<26;scanf("%d",&ar[i++]));
tn=0;dfs(0,0,0),dfs(1,0,0);sort(xr,xr+tn,bimp);
for(i=j=0;;++i){
j+=xr[i].b;
if(j>=k){printf("%I64d\n",xr[i].a);break;}
}
}
putchar('\n');
};
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int t;for(_clfr(),scanf("%d",&t);t;t--,cl());
return 0;
};