参考了网上的思路,第一次写hash, 写得很纠结 ,结果因为统计的时候超int了,调到想死。。。
ACcode:
#include<map>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int PR=37;
const int NS=111110;
const int MOD=777777777;
struct Node{
LL x;
int l,r,d;
Node(){}
Node(LL _x,int _l,int _r,int _d){
x=_x,l=_l,r=_r,d=_d;
}
bool operator < (const Node &cmp)const{
return l>cmp.l;
}
}s[NS];
int n,m;
int v[30];
int p[NS<<1];
char str[NS],c[NS<<1];
LL pv[NS];
LL shine[NS],k;
LL por[NS],pom[NS];
map<LL,LL> sco;
map<LL,LL>::iterator it;
map<pair<LL,int>,int> hs;
LL get(int l,int r)
{
return shine[r]-shine[l-1]*por[r-l+1];
}
LL getv(int l,int r)
{
return (pv[r]-(pv[l-1]*pom[r-l+1]%MOD)+MOD)%MOD;
}
void solve()
{
int top=1;
c[0]='$',c[1]='#';
for (int i=1;i<=n;i++)
{
c[++top]=str[i];
c[++top]='#';
}
c[top+1]='\0';
int idm,rm=0;
for (int i=1;i<top;i++)
{
if (rm>i)
p[i]=min(rm-i,p[idm*2-i]);
else
p[i]=1;
for (;c[i+p[i]]==c[i-p[i]];p[i]++);
if (p[i]+i>rm)
rm=p[i]+i,idm=i;
}
hs.clear();
int pos,cnt=0;
for (int i=2;i<top;i++)
{
int r=i>>1;
int l=(i-p[i]+2)>>1;
for (;l<=r;l++)
{
LL x=get(l,r);
pos=hs[make_pair(x,r-l+1)];
if (!pos)
{
s[++cnt]=Node(x,r-l+1,r,1);
hs[make_pair(x,r-l+1)]=cnt;
}
else
{
s[pos].d++;
break;
}
}
}
sort(s+1,s+cnt+1);
for (int i=1;i<=cnt;i++)
hs[make_pair(s[i].x,s[i].l)]=i;
for (int i=1;i<=cnt;i++)
{
int r=s[i].r;
int l=r-s[i].l+1;
if (l<r)
{
LL x=get(l+1,r);
pos=hs[make_pair(x,r-l)];
s[pos].d+=s[i].d-1;
}
}
for (;m--;)
{
scanf("%I64d",&k);
for (int i=0;i<26;i++)
scanf("%d",&v[i]);
pv[0]=0;
for (int i=1;i<=n;i++)
pv[i]=pv[i-1]*26+v[str[i]-'a'],pv[i]%=MOD;
sco.clear();
for (int i=1;i<=cnt;i++)
{
int r=s[i].r;
int l=r-s[i].l+1;
LL x=getv(l,r);
sco[x]+=s[i].d;
}
LL ans;
for (it=sco.begin();it!=sco.end();it++)
{
LL num=it->second;
if (k<=num)
{
ans=it->first;
break;
}
else
k-=num;
}
printf("%I64d\n",ans);
}
puts("");
}
int main()
{
int T;
por[0]=pom[0]=1;
for (int i=1;i<NS;i++)
por[i]=por[i-1]*PR,
pom[i]=pom[i-1]*26%MOD;
for (scanf("%d",&T);T--;)
{
scanf("%d %d %s",&n,&m,str+1);
shine[0]=0;
for (int i=1;i<=n;i++)
shine[i]=shine[i-1]*PR+(str[i]-'a');
solve();
}
return 0;
}