题目分析:
本蒟蒻的想法 :trie树+(dfs序+主席树 || 线段树合并)
把每个串的所有后缀的个数和是O(n)的。
直接把每个后缀都插入哈希表里。开vector存一个哈希值对应的所有编号。
Code:
#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
#define LL long long
#define maxn 100005
#define maxp maxn*30
using namespace std;
char cb[1<<18],*cs,*ct;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<18,stdin),cs==ct)?0:*cs++)
inline void read(int &a){
char c;while(!isdigit(c=getc()));
for(a=c-'0';isdigit(c=getc());a=a*10+c-'0');
}
struct HashMap{
const static int mod = 100007;
const static int maxm = 100005;
int fir[maxn],nxt[maxm],val[maxn],tot;
int insert(int x){
int u=(x%mod+mod)%mod;
for(int i=fir[u];i;i=nxt[i]) if(val[i]==x) return i;
nxt[++tot]=fir[u],fir[u]=tot,val[tot]=x;
return tot;
}
}H;
int n,h[maxn];
char s[maxn];
vector<int>a[maxn];
int main()
{
#ifndef ONLINE_JUDGE
freopen("H.in","r",stdin);
#endif
read(n);
for(int i=1;i<=n;i++){
while(!isalpha(s[0]=getc()));
int len=1;while(isalpha(s[len]=getc())) len++;
for(int j=len-1;j>=0;j--){
h[i]=h[i]*137+s[j];
a[H.insert(h[i])].push_back(i);
}
}
for(int i=1,k;i<=n;i++){
read(k);int j=H.insert(h[i]);
if(k>a[j].size()) puts("-1");
else printf("%d\n",a[j][k-1]);
}
}