之前一直沒怎麼關心字符串的相關數據結構,最近心血來潮就想學一下,昨天看了下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;
}