BZOJ 3439: Kpm的MC密码 【哈希】

题目传送门

题目分析:

本蒟蒻的想法 :trie树+(dfs序+主席树 || 线段树合并)

dalao学长的想法:直接哈希

把每个串的所有后缀的个数和是O(n)的。
直接把每个后缀都插入哈希表里。开vector存一个哈希值对应的所有编号。

Code:

#include
#include
#include
#include
#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]);
	}
}

你可能感兴趣的:(哈希)