字典树
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;
}
把“查询的字符串”构成字典树,然后查询“给出的字符串”中包含了哪些“查询的字符串”。
#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;
}

浙公网安备 33010602011771号