字典树 总结
初学
用数组来建树
// 用数组模拟 一般优于结构体
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
using namespace std;
const int maxn = 1e5 + 10;
int tire[maxn][26]; //字典树, 数组建树
int exist[maxn];//单词是否为输入的
int sum[maxn];//包含相同前缀数,即该点经过次数
int tot = 0;
void insert(char *s){//插入
int len = strlen(s);
int root = 0;
for(int i = 0; i < len; ++ i){
int id = s[i] - 'a';
if(tire[root][id] == -1){
tire[root][id] = ++ tot;
exist[tot] = 0;
}
root = tire[root][id];
sum[root] ++;
}
exist[root] = 1;//该节点是存入的单词最后一位,表示该单词是存在的
}
//查找有 查找单词是否存在 和 查找前缀
int find(char *s){//查找是否为插入单词
int len = strlen(s);
int root = 0;
for(int i = 0; i < len; ++ i){
int id = s[i] - 'a';
if(tire[root][id] == -1)//不存在
return -1;
root = tire[root][id];
}
if(exist[root] == 1)//如果只是查找前缀的话,就不需要判断exist了
return 1;
else
return -1;
}
int find_num(char *s){//查找前缀s出现的次数
int len = strlen(s);
int root = 0;
for(int i = 0; i < len; ++ i){
int id = s[i] - 'a';
if(tire[root][id] == -1)//不存在
return 0;
root = tire[root][id];
}
return sum[root];
}
void delete(char *s){
int len = strlen(s);
int rt = 0, cnt = 0;
int num[1000], rt = 0;
for(int i = 0; i < len; ++ i){
int id = s[i] - 'a';
rt = tire[rt][id];
if(sum[rt] == 1){//存单路节点, 到时候可以删除,多个分支就不可删
num[cnt] = rt;
cnt ++;
}
else
st = rt;
}
exist[id] = 0;
for(int i = 0; i < cnt; ++ i){
tire[st][num[i]] = 0;
st = num[i];
}
}
用结构体 与 指针建树
//用结构体 与 指针来建树
typedef struct tire{
int sum, exist;
tire *next[26],
}tire;
tire *root;
tire *build(){
tire *k = new(tire);
k->sum=0;
memset(k->next,0,sizeof(k->next));
return k;
}
void insert(char *s){
tire *r = root;
char *word = s;
while(*word){
int id = *word - 'a';
if(r->next[id] == NULL)
r->next[id] = build();
r = r->next[id];
r->sum ++;
word ++;
}
r->exist = 1;
}
int search(char *s){
tire *r = root;
char *word = s;
while(*word){
int id = *word - 'a';
if(r->next[id] == NULL)
return 0;
r->next[id];
word ++;
}
//return r->exist;
return r->sum;
}
题目
hdu 1251 模板题
//数组
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn = 1e6 + 10;
int tire[maxn][26];
int sum[maxn];
int tot = 0;
void insert(char *s){
int len = strlen(s);
int rt = 0;
for(int i = 0; i < len; ++ i){
int id = s[i] - 'a';
if(tire[rt][id] == 0)
tire[rt][id] = ++ tot;
rt = tire[rt][id];
sum[rt] ++;
}
}
int search_sum(char *s){//查找前缀出现次数
int len = strlen(s);
int rt = 0;
for(int i = 0; i < len; ++ i){
int id = s[i] - 'a';
if(tire[rt][id] == 0)
return 0;
rt = tire[rt][id];
}
return sum[rt];
}
char s[20];
int main(){//两种读入判断 空行 的方法
//while(cin.getline(s,12)){
// if(strlen(s) == 0)
// break;
//
//}
while(gets(s)){//空行。gets读入的回车符会自动转换为NULL。
if(s[0] == NULL)
break;
insert(s);
}
while(~scanf("%s", s)){
printf("%d\n", search_sum(s));
}
}
//结构体
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef struct tire{
int sum, exist;
tire *next[26];
}tire;
tire *root;
tire *build(){
tire *k = new(tire);
for(int i = 0; i < 26; ++ i)
k->next[i] = NULL;
k->sum = 0;
return k;
}
void insert(char *s){
tire *r = root;
int len = strlen(s);
for(int i = 0; i < len; ++ i){
int id = s[i] - 'a';
if(r->next[id] == NULL)
r->next[id] = build();
r = r->next[id];
r->sum ++;
}
}
int find(char *s){
tire *r = root;
int len = strlen(s);
for(int i = 0; i < len; ++ i){
int id = s[i] - 'a';
if(r->next[id] == 0)
return 0;
r = r->next[id];
}
return r->sum;
}
char s[20];
int main(){
root = build();
while(gets(s)){
if(s[0] == NULL)
break;
insert(s);
}
while(~scanf("%s", s)){
printf("%d\n", find(s));
}
}
hdu 2072
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 2e6 + 10;
int tire[maxn][26];
int exist[maxn];
int ans = 0;
int tot = 0;
void insert(char *s){
int len = strlen(s);
int rt = 0;
for(int i = 0; i < len; ++ i){
int id = s[i] - 'a';
if(tire[rt][id] == 0){
tire[rt][id] = ++ tot;
exist[tot] = 0;
}
rt = tire[rt][id];
}
if(exist[rt] == 0){
ans ++;//ans 记录出现次数,去除重复
exist[rt] = 1;
}
}
char s[maxn];
char temp[maxn];
int main(){
while(gets(s)){
ans = 0;
exist[0] = 0;
if(s[0] == '#')
break;
int len = strlen(s);
int cnt = 0;
for(int i = 0; i < len; ++ i){
if(s[i] != ' ')
temp[cnt ++] = s[i];
else{
temp[cnt] = '\0';
if(temp[0] != '\0')
insert(temp);
cnt = 0;
}
}
if(temp[0] != '\0')
insert(temp);
printf("%d\n", ans);
for(int i = 0; i <= tot; ++ i)
exist[i] = 0;
}
}
将输入的字符串按字典序排序小到大输出
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e6 + 10;
int tire[maxn][26];
int exist[maxn];
int tot = 0;
void insert(char *s){
int len = strlen(s);
int rt = 0;
for(int i = 0; i < len; ++ i){
int id = s[i] - 'a';
if(tire[rt][id] == 0){
tire[rt][id] = ++ tot;
exist[tot] = 0;
}
rt = tire[rt][id];
}
exist[rt] = 1;
}
char temp[maxn];
void sort_string(int rt, int cnt){// 按字典序排序输出
for(int i = 0; i < 26; ++ i){
int ccnt = cnt;
if(tire[rt][i] != 0){
temp[ccnt ++] = 'a' + i;
temp[ccnt] = '\0';
if(exist[tire[rt][i]] == 1)
printf("%s\n", temp);
sort_string(tire[rt][i], ccnt);
}
}
}
char s[maxn];
int main(){
while(~scanf("%s", s)){
insert(s);
}
sort_string(0, 0);
}
POJ 2001
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e6 + 10;
int tire[maxn][26];
int sum[maxn];
int tot = 0;
void insert(char *s){
int len = strlen(s);
int rt = 0;
for(int i = 0; i < len; ++ i){
int id = s[i] - 'a';
if(tire[rt][id] == 0)
tire[rt][id] = ++ tot;
rt = tire[rt][id];
sum[rt] ++;
}
}
void print_shortest_prefix_substring(char *s){//输出最短的代表自己的字符串
int len = strlen(s);
int rt = 0;
char temp[22];
int cnt = 0;
for(int i = 0; i < len; ++ i){
int id = s[i] - 'a';
rt = tire[rt][id];
if(sum[rt] != 1)
temp[cnt ++] = id + 'a';
else{
temp[cnt ++] = id + 'a';
break;
}
}
temp[cnt] = '\0';
printf("%s\n", temp);
}
char s[1010][22];
int main(){
int cnt = 0;
while(~scanf("%s", s[cnt])){
insert(s[cnt++]);
}
for(int i = 0; i < cnt; ++ i){
printf("%s ", s[i]);
print_shortest_prefix_substring(s[i]);
}
}
POJ 3630
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 1e6 + 10;
int tire[maxn][10];
int sum[maxn];
int exist[maxn];
int tot = 0;
int flag = 1;
void insert(char *s){
int len = strlen(s);
int rt = 0;
for(int i = 0; i < len; ++ i){
int id = s[i] - '0';
if(tire[rt][id] == 0){
tire[rt][id] = ++ tot;
exist[tot] = 0;
}
rt = tire[rt][id];
sum[rt] ++;
if(exist[rt] == 1)//只要在某个字符串路径上出现其他串的最后一位,flag=0
flag = 0;
}
exist[rt] = 1;
if(exist[rt] == 1 && sum[rt] > 1)
flag = 0;
}
void init_tire(int rt){//初始化
for(int i = 0; i < 10; ++ i){
if(tire[rt][i]){
inittire(tire[rt][i]);
tire[rt][i] = 0;
}
}
}
int t, n;
char s[20];
int main(){
scanf("%d", &t);
while(t--){
scanf("%d", &n);
flag = 1;
tot = 0;
for(int i = 0; i < n; ++ i){
scanf("%s", s);
insert(s);
}
if(flag)
printf("YES\n");
else
printf("NO\n");
for(int i = 0; i <= tot; ++ i){
sum[i] = 0;
exist[i] = 0;
}
init_tire(0);
}
}
light oj 1224
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 2e6 + 10;
int tire[maxn][4];
int sum[maxn];
int maxx = 0;
int tot = 0;
void insert(char *s){
int len = strlen(s);
int rt = 0;
for(int i = 0; i < len; ++ i){
int id = 0;
if(s[i] == 'C')
id = 1;
else if(s[i] == 'G')
id = 2;
else if(s[i] == 'T')
id = 3;
if(tire[rt][id] == 0)
tire[rt][id] = ++ tot;
rt = tire[rt][id];
sum[rt] ++;
if(sum[rt] * (i + 1) > maxx)
maxx = sum[rt] * (i + 1);
}
}
int n, t;
char s[52];
int main(){
int cnt = 1;
for(scanf("%d", &t); t; --t){
scanf("%d", &n);
tot = 0;
maxx = 0;
for(int i = 0; i < n; ++ i){
scanf("%s", s);
insert(s);
}
printf("Case %d: %d\n", cnt++, maxx);
for(int i = 0; i <= tot; ++ i){
sum[i] = 0;
for(int j = 0; j < 4; ++ j)
tire[i][j] = 0;
}
}
}
POJ1451
#include<cstdio>
#include<map>
#include<cstring>
#include<algorithm>
#include<string>
#include<iostream>
using namespace std;
const int maxn = 1e6 + 10;
int tire[maxn][26];
int sum[maxn];
map<string, int> map1;
map<string, string> map2;
int alpha_to_int[30];
int tot;
void init(){
for(int i = 0; i <= 17; ++ i)
alpha_to_int[i] = i / 3 + 2;
alpha_to_int[18] = 7;
for(int i = 19; i < 25; ++ i)
alpha_to_int[i] = (i-1) / 3 + 2;
alpha_to_int[25] = 9;
}
void insert(char *s, int num){
int len = strlen(s);
int rt = 0;
string temp_int = "", temp_alpha = "";
for(int i = 0; i < len; ++ i){
int id = s[i] - 'a';
temp_int += alpha_to_int[id] + '0';
temp_alpha += id + 'a';
if(tire[rt][id] == 0)
tire[rt][id] = ++ tot;
rt = tire[rt][id];
sum[rt] += num;
if(sum[rt] > map1[temp_int]){
map1[temp_int] = sum[rt];
map2[temp_int] = temp_alpha;
}
}
}
int t, n, num;
char s[110];
int main(){
int cnt = 1;
init();
for(scanf("%d", &t); t; --t){
map1.clear();
map2.clear();
scanf("%d", &n);
tot = 0;
for(int i = 0; i < n; ++ i){
scanf("%s %d", s, &num);
insert(s, num);
}
scanf("%d", &n);
printf("Scenario #%d:\n", cnt ++);
for(int i = 0; i < n; ++ i){
scanf("%s", s);
int len = strlen(s);
string temp = "";
for(int j = 0; j < len-1; ++ j){
temp += s[j];
if(!map2.count(temp))//map1[temp])
printf("MANUALLY\n");
else
printf("%s\n",map2[temp].c_str());
//cout << map2[temp] << endl;
}
printf("\n");
}
printf("\n");
for(int i = 0; i <= tot; ++ i){
sum[i] = 0;
for(int j = 0; j < 26; ++ j)
tire[i][j] = 0;
}
}
}