【题解】【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;
}