字典树

1.hdoj 1251 统计哪题

初级字典树,建树,插入,查询。

 

代码
#include <iostream>
#include
<cstdio>
#include
<cstring>
using namespace std;

struct Trie{
int cnt;
Trie
* next[26];
Trie():cnt(
0){ for(int i=0; i<26; ++i) next[i] = NULL; }
}
*head;

void update(char ch[]){
int len, i;
Trie
*s, *temp;
len
= strlen(ch);
s
= head;
for(i=0; i<len; ++i){
if(s -> next[ch[i] - 'a'] == NULL){
temp
= new Trie;
s
-> next[ch[i] - 'a'] = temp;
}
s
= s -> next[ch[i] - 'a'];
(s
-> cnt) ++;
}
}

int query(char ch[]){
int i, len, ans;
Trie
* s;
s
= head;
len
= strlen(ch);
for(i=0; i<len; ++i){
if(s -> next[ch[i] - 'a'] == NULL){
return 0;
}
else{
s
= s -> next[ch[i] - 'a'];
ans
= s -> cnt;
}
}
return ans;
}

void del(Trie *s){
for(int i=0; i<26; ++i){
if(s->next[i] != NULL)
del(s
->next[i]);
}
delete s;
}

int main(){
// freopen("c:/aaa.txt", "r", stdin);
char ch[15];
head
= new Trie;
while(gets(ch)){
if(strcmp(ch, "") == 0) break;
update(ch);
}
while(gets(ch)){
printf(
"%d\n", query(ch));
}
del(head);
return 0;
}

2.hdoj 1671 Phone List

插入时,有没有遇到前一个号码,或者现在这个号码是不是之前号码的子串。 

 

代码
#include <iostream>
#include
<cstdio>
#include
<cstring>
using namespace std;

struct Trie{
Trie
*next[10];
int cnt;
bool end;
Trie():cnt(
0),end(0){ for(int i=0; i<10; ++i) next[i] = NULL; }
}
*head;

bool insert(char ch[]){
int i, j, len;
Trie
*s, *temp;

s
= head;
len
= strlen(ch);
for(i=0; i<len; ++i){
if(s->next[ch[i]-'0'] == NULL){
temp
= new Trie;
s
->next[ch[i]-'0'] = temp;
}

s
= s->next[ch[i]-'0'];
if(s->end != 0) return 0;
if(i == len-1 && s->cnt != 0) return 0;
s
->cnt ++;
if(i == len-1) s->end = 1;
}
return 1;
}

void del(Trie* s){
int i;
for(i=0; i<10; ++i){
if(s->next[i] != NULL){
del(s
->next[i]);
}
}
delete s;
}

int main(){
// freopen("c:/aaa.txt", "r", stdin);
int T, n;
bool flag;
char ch[100];

scanf(
"%d", &T);
while(T--){
scanf(
"%d", &n);
flag
= 1;
head
= new Trie;
while(n--){
scanf(
"%s", ch);
if(flag) flag = insert(ch);
}
(flag)
? puts("YES") : puts("NO");
del(head);
}
return 0;
}

3.hdoj 1800 Flying to the Mars

没看见数据里还有个04,哎,看题太不仔细了。。。。

 

代码
#include <iostream>
#include
<cstdio>
#include
<cstring>
using namespace std;

struct Trie{
int cnt;
Trie
*next[10];
Trie():cnt(
0){for(int i=0; i<10; ++i) next[i] = NULL; }
}
*head;

int ans;

void insert(char ch[]){
Trie
*s, *temp;
int len, i, j;
len
= strlen(ch);

for(i=0; i<len; ++i) if(ch[i] > '0' && ch[i] <= '9') break;
if(i == len){
strcpy(ch,
"0");
j
= 1;
}
else{
for(j=0; i<len; ++i){
ch[j
++] = ch[i];
}
}

len
= j;
s
= head;
for(i=0; i<len; ++i){
if(s -> next[ch[i] - '0'] == NULL){
temp
= new Trie;
s
-> next[ch[i] - '0'] = temp;
}
s
= s -> next[ch[i] - '0'];
if(i == len-1){
s
->cnt ++;
if(s -> cnt > ans) ans = s -> cnt;
}
}
}

void del(Trie *s){
for(int i=0; i<10; ++i){
if(s -> next[i] != NULL)
del(s
-> next[i]);
}
delete s;
}

int main(){
// freopen("c:/aaa.txt", "r", stdin);
char ch[32];
int n;
while(scanf("%d", &n)!=EOF){
ans
= 0;
head
= new Trie;
while(n--){
scanf(
"%s", ch);
insert(ch);
}
printf(
"%d\n", ans);
del(head);
}
return 0;
}

4.hdoj 1247 Hat’s Words

刚开始的做法是将两个单词拼成一个单词,然后查找这个单词。而没想到将一个单词分成两个单词,

然后查找这两个单词。前一种的规模是50,000 * 50,000 * 50 ,后一种50,000 * 50 * 50。

搜索策略改一点点就很不一样呀。

代码
#include <iostream>
#include
<cstdio>
#include
<cstring>
using namespace std;

struct Trie{
Trie
*next[26];
bool end;
Trie():end(
0){ for(int i=0; i<26; ++i) next[i] = NULL; }
}
*head;

char str[50010][100];
int n;

void insert(char ch[]){
int len, i;
Trie
*s, *temp;
s
= head;
len
= strlen(ch);
for(i=0; i<len; ++i){
if(s -> next[ch[i] - 'a'] == NULL){
temp
= new Trie;
s
-> next[ch[i] - 'a'] = temp;
}
s
= s -> next[ch[i] - 'a'];
if(i == len - 1){
s
-> end = 1;
}
}
}

bool query(char ch[]){
int len, i;
Trie
*s;
s
= head;
len
= strlen(ch);
for(i=0; i<len; ++i){
if(s -> next[ch[i] - 'a'] == NULL) return 0;
s
= s -> next[ch[i] - 'a'];
if(i == len - 1 && s -> end == 1) return 1;
}
return 0;
}

int main(){
// freopen("c:/aaa.txt", "r", stdin);
char ch1[100], ch2[100];
int idx, i, j, k, len;
head
= new Trie;
idx
= 0;
while(scanf("%s", &str[idx])!=EOF){
insert(str[idx]);
++idx;
}

n
= idx;
for(i=1; i<n; ++i){
len
= strlen(str[i]);
for(j=1; j<len; ++j){
for(k=0; k<j; ++k){
ch1[k]
= str[i][k];
}
ch1[k]
= '\0';

idx
= 0;
for(k=j; k<len; ++k){
ch2[idx
++] = str[i][k];
}
ch2[idx]
= '\0';

if(query(ch1) && query(ch2)){
puts(str[i]);
break;
}
}
}

return 0;
}

5.hdoj 2846 Repository 

把“查询的字符串”构成字典树,然后查询“给出的字符串”中包含了哪些“查询的字符串”。

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

struct Trie {
	int end;
	Trie* next[26];
	Trie():end(-1) { for(int i=0; i<26; ++i) next[i] = NULL; }
};

Trie *head;


int n, m;
char _s[10002][22];
bool mark[100002];
int ans[100002];
int father[100002];


void insert(char ch[], int id) {
	int i, len;
	Trie *now, *temp;
	now = head;
	len = strlen(ch);
	for(i=0; i<len; ++i) {
		if(now->next[ch[i]-'a'] == NULL) {
			temp = new Trie;
			now->next[ch[i]-'a'] = temp;
		}
		now = now->next[ch[i]-'a'];
		if(i == len - 1) {
			if(now->end >= 0) father[id] = now->end;
			else now->end = id;
		}
	}
}


void query(char ch[]) {
	int i, len;
	Trie *now;
	now = head;
	len = strlen(ch);
	for(i=0; i<len; ++i) {
		if(now->next[ch[i] - 'a'] == NULL) return;
		now = now->next[ch[i] - 'a'];
		if(now->end >= 0 && mark[now->end] == 0) {
			mark[now->end] = 1;
			ans[now->end] ++;
		}
	}
}

			


void solve(int x) {
	int i, len;
	len = strlen(_s[x]);
	for(i=0; i<len; ++i) {
		query(_s[x]+i);
	}
}



void myfree(Trie *now) {
	int i;
	for(i=0; i<26; ++i) {
		if(now->next[i] != NULL) {
			myfree(now->next[i]);
			delete now->next[i];
		}
	}
}



int main() {
//	freopen("c:/aaa.txt", "r", stdin);
	int i, j;
	char ch[25];
	scanf("%d", &n);
	for(i=0; i<n; ++i) scanf("%s", _s[i]);
	
	head = new Trie;
	scanf("%d", &m);
	for(i=0; i<m; ++i) {
		ans[i] = 0;
		father[i] = i;
		scanf("%s", ch);
		insert(ch, i);
	}

	for(i=0; i<n; ++i) {
		for(j=0; j<m; ++j) mark[j] = 0;
		solve(i);
	}

	for(i=0; i<m; ++i) 
		printf("%d\n", ans[father[i]]);
	myfree(head);
	return 0;
}



 

 

 

posted on 2010-11-13 09:40  CrazyAC  阅读(236)  评论(0)    收藏  举报