字典树,就是树形的字母排列,从根节点开始(根节点不代表任何字母),它的每一个子节点都有一个不同的字母,这样,从根节点开始沿任何路径到达一个叶子节点,路过的字母组合就是一个字符串,字典树在字符串的存储和查找上有很大的优越性,下面是用字典树写的两个题。
hdu 1251
/* 这道题就是标准的字典树,存储给出的所有的在字典中给出的字符串和其前缀,统计其数目,存储在字典树中,然后就可以在O(len(m))的时间内查询给出的模式串的答案了 */ #include<stdio.h> #include<string.h> #include<stdlib.h> struct Trie{ int v; struct Trie *next[26]; } root; void creat(char *str) { int len = strlen(str); struct Trie *p = &root,*q; for (int i = 0; i< len; i++){ int id = str[i] - 'a'; if (p->next[id] == NULL){ q = (Trie *)malloc(sizeof(root)); q->v = 1; for (int j = 0; j< 26; j++) q->next[j] = NULL; p->next[id] = q; p = p->next[id]; } else { p->next[id]->v++; p = p->next[id]; } } } int search(char *str) { int len = strlen(str); struct Trie *p; p = &root; for (int i = 0; i< len; i++){ int id = str[i] - 'a'; p = p->next[id]; if (p == NULL) return 0; } return p->v; } int main() { char str[15]; int i; for (i = 0; i< 26; i++) root.next[i] = NULL; while (gets(str) && str[0] != '\0') creat(str); memset(str,0,sizeof(str)); while (scanf ("%s",&str) != EOF){ int ans = search(str); printf ("%d\n",ans); } return 0; } pku 1204
这一题我纠结了n久,本来改用AC自动机的(下一篇博客里讲),因为数据规模的原因,字典树都能暴过,而且由于我的AC自动机学的不怎么的,两个程序跑的时间差不多。。。。
/* 这一题用字典树纯属数据的原因,对所给的模式串建树,再对原图中每个节点的八个方向进行匹配,没有超时很是奇怪 */ #include<stdio.h> #include<string.h> #include<stdlib.h> struct Trie{ int count; struct Trie *fail; struct Trie *next[26]; } *root,*queue[500005]; int n,m,result[1005][2]; char map[1005][1005],ans[1005]; int dir[8][2] = {{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}}; void insert(char *s,int k) { int len = strlen(s),i; struct Trie *p = root,*q; for (i = 0; i< len; i++){ int id = s[i] - 'A'; if (p->next[id] == NULL){ q = (struct Trie *)malloc(sizeof(Trie)); memset(q->next,NULL,sizeof(q->next)); q->count = -1; p->next[id] = q; p = q; } else p = p->next[id]; } p->count = k; } void search(int x,int y,int k) { int x1 = x,y1 = y; struct Trie *p = root; while (x1 >= 0 && y1 >= 0 && x1 < n && y1 < m){ int id = map[x1][y1] - 'A'; if (p->next[id] == NULL) break; else p = p->next[id]; if (p ->count != -1){ result[p->count][0] = x; result[p->count][1] = y; ans[p->count] = k + 'A'; p->count = -1; } x1 += dir[k][0]; y1 += dir[k][1]; } } void solve(int sum) { int i,j,k; for (i = 0; i< n; i++) for (j = 0; j< m; j++) for (k = 0; k< 8; k++) search(i,j,k); for (i = 0; i < sum; i++) printf ("%d %d %c\n",result[i][0],result[i][1],ans[i]); } int main() { int i,k; char word[2005]; scanf ("%d%d%d",&n,&m,&k); memset(map,0,sizeof(map)); root = (struct Trie *)malloc(sizeof(Trie)); memset(root->next,NULL,sizeof(root->next)); for (i = 0; i < n; i++) scanf ("%s",&map[i]); getchar(); for (i = 0; i< k; i++){ gets(word); insert(word,i); } solve(k); return 0; }