【题解】【bzoj1819】【JSOI】Word Query电子字典

屑人屑题解。

做完去题解区翻了一波,全是没想到的Trie。

表示只会字符串hash /kel。

懒得写格式了。

首先,维护两个umap(其实是代替umset的),一个是单词表,一个是变化过的单词表。

变化过的单词表分两种:原单词删去一个字母和原单词把一个字母改成 $

查询的时候先看单词表里有没有,没有的话,先直接在变化表里查一个,再选一个字母删掉再查一个,再把一个字母改成 $ 再查一个。

注意,为了防止出现一些奇奇怪怪的重复,插入和查询时需要一个uset来去重

为什么不直接用umap存字符串而还要先hash再存?空间问题~

上代码吧

#include<bits/stdc++.h>
#pragma GCC optimize("Ofast",3,"inline")
using namespace std;
typedef pair<unsigned long long,unsigned long long>ul;//双哈希,稳
struct hasher{
	size_t operator()(const ul p)const{
		return (hash<unsigned long long>()(p.first)*13148274ull+hash<unsigned long long>()(p.second))%86850899ull;
	}
};
unordered_map<ul,int,hasher>umap,dict;
ul strhash(string x){
	unsigned long long ret1=0,ret2=0;
	for(auto i:x)ret1=(ret1*INT_MAX+i)%23333333;
	for(auto i:x)ret2=ret2*998244353ull+i;
	return make_pair(ret1,ret2);
}
void insert(string x){
	++dict[strhash(x)];
	unordered_set<ul,hasher>uset;
	for(unsigned i=0;i<x.length();++i){
		auto p(x);
		p[i]='$';
		++umap[strhash(p)];
	}
	for(unsigned i=0;i<x.length();++i){
		auto p(x);
		p.erase(p.begin()+i);
		uset.insert(strhash(p));
	}
	for(auto w:uset)++umap[w];
}
int query(string x){
	const ul w=strhash(x);
	if(dict[w])return -1;
	unordered_set<ul,hasher>uset;
	int ans=umap[w];
	for(unsigned i=0;i<x.length();++i){
		auto p(x);
		p.erase(p.begin()+i);
		uset.insert(strhash(p));
	}
	for(unsigned i=0;i<x.length();++i){
		auto p(x);
		p[i]='$';
		ans+=umap[strhash(p)];
	}
	for(auto l:uset)ans+=dict[l];
	return ans;
}
int main(){
	int n,m;cin>>n>>m;
	for(int i=1;i<=n;++i){
		string x;cin>>x;
		insert(x);
	}
	for(int i=1;i<=m;++i){
		string x;cin>>x;
		cout<<query(x)<<endl;
	}
	return 0;
}
posted @ 2020-09-23 21:01  UnyieldingTrilobite  阅读(124)  评论(0编辑  收藏  举报