之前一直没怎么关心字符串的相关数据结构,最近心血来潮就想学一下,昨天看了下manacher,感觉只是一个思想而已,并不是很难,然后又想起以前只是听过的字典树,大概知道是个什么意思,一直没来亲手实现过,趁着中午没课就自己敲了一下,发现实现也不难,大概写了15min吧,就是感觉自己的代码有点难看2333,试写了一下hihocoder的hiho一下的题过了,还是挺高兴吧。
字典树应用的话最基本最普遍的也就是字典中查单词了吧,思想的话就是利用字符串的公共前缀来降低查询时间来提高效率,以给出的字典中的单词来建树,如下面这个例子,abcd和abd共用前缀ab,那么就像下面这样画树。
(图网上找的)
下面附上我写的辣鸡代码(这么写着方便,但肯定不快,就当留着做个纪念2333
(http://hihocoder.com/problemset/problem/1014 这个的ac代码)
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define EPS 1e-7
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
using namespace std;
typedef long long LL;
typedef pair<LL, LL> P;
const int maxn = 1e5 + 5;
const int mod = 1e8 + 7;
int n,m;
int L[maxn<<2];
struct edge{
int to;
char weight;
};
vector<edge>tree[maxn<<2];
int tmp;
void init(){
tmp=1;
memset(L,0,sizeof(L));
for (int i=0;i<maxn;i++) tree[i].clear();
}
void add(char *s){
int i=1,j=0,k;
while (j!=strlen(s)){
bool flag=0;
for (k=0;k<tree[i].size();k++){
if (tree[i][k].weight==s[j]) {
flag=1;
break;
}
}
if (flag){
i=tree[i][k].to;
j++;
L[i]++;
}
else {
tree[i].push_back({++tmp,s[j]});
L[tmp]++;
i=tmp;
j++;
}
}
}
int query(char *s){
int i=1,j=0,k;
while (j!=strlen(s)){
bool flag=0;
for (k=0;k<tree[i].size();k++){
if (tree[i][k].weight==s[j]) {
flag=1;
break;
}
}
if (flag){
i=tree[i][k].to;
j++;
}
else return 0;
}
return L[i];
}
char s[15];
int main (){
scanf ("%d",&n);
init();
for (int i=0;i<n;i++){
scanf ("%s",s);
add(s);
}
scanf ("%d",&m);
for (int i=0;i<m;i++){
scanf ("%s",s);
int ans=query(s);
printf ("%d\n",ans);
}
return 0;
}