trie字典树

 字典树,顾名思义,是一个树形结构。有唯一的根节点。每次插入一个字符串的时候,首先扫描字符串,然后从第一个字符开始逐个插入。

例如: 插入字符串 "abcd"
            1、一定是从根节点开始,用一个节点p指向根节点。
            2、首先判断p是否有一个子节点指向字符当前字符(第一个就是'a'),如果没有就新建一个子节点,并且将trie[p][a]指向新建节点,将当前的指针指向新建节点,否则就直接指向该节点。
            3、继续遍历下一个字符,重复步骤 2。
            4、在插入最后一个字符的时候,将节点p正在end[N]中进行标记,表示该节点是一个字符串结束的位置,目的是为了检索的方便。

检索字符串的时候也按照插入的方式一个个字符向下走就可以了。用一个end[ N]数组来标记插入的每一个字符串的结束位置,如果检索字符串检索到了(即路径上没有空节点),且最后一个字符所在的节点在end[N]中被标记了,那么说明该字符串存在过。

#include <bits/stdc++.h>
#pragma warning (disable:4996)
#pragma warning (disable:6031)
#define mem(a, b) memset(a, b, sizeof a)
using namespace std;
const int N = 310;
int trie[N][26];
int cnt;
int root;
bool nd[N];
void insert(char* s) {
	int len = strlen(s);
	int p = root;
	for (int i = 0; i < len; i++) {
		if (trie[p][s[i] - 'a'] == 0) {
			++cnt;
			trie[p][s[i] - 'a'] = cnt;
		}
		p = trie[p][s[i] - 'a'];
	}
	nd[p] = 1;
}
bool check(char* s) {
	int len = strlen(s);
	int p = root;
	for (int i = 0; i < len; i++) {
		if (trie[p][s[i] - 'a'] == 0)return false;
		p = trie[p][s[i] - 'a'];
	}
	return nd[p];
}
int main()
{
	root = 0;
	cnt = 0;
	mem(nd, 0);
	mem(trie, 0);
	char s[10];
	for (int i = 0; i < 5; i++) {
		scanf("%s", s);
		insert(s);
	}
	for (int i = 0; i < 10; i++) {
		scanf("%s", s);
		if (check(s)) {
			printf("Yes : %s\n", s);
		}
		else printf("NO : Sorry\n");
	}
	return 0;
}

 

posted @ 2020-02-24 11:29  correct  阅读(98)  评论(0)    收藏  举报