hdu-1247 Hat’s Words---字典树模板

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1247

题目大意:

给出一些单词,以EOF结束,看其中哪一个单词可以由其他两个单词组成,将其输出

解题思路:

将所有单词存入字典树中,每个单词拆成两部分查询是不是字典树中的单词。

此处是查询是不是单词,需要加单词标记数组,在每个单词最后一位的末尾那个节点标记true

传送门:字典树模板

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<map>
 6 #include<set>
 7 #include<cmath>
 8 #include<algorithm>
 9 #include<vector>
10 #include<sstream>
11 #define lowbot(i) (i&(-i))
12 using namespace std;
13 
14 const int maxn = 1e6 + 10;
15 int tree[maxn][26];
16 //字典树tree[u][v]表示编号为u的节点的下一个字母为v连接的节点的编号
17 int idx(char c){ return c - 'a'; }//可以写成宏定义
18 int tot = 1;//根节点编号为1
19 bool is_word[maxn];//单词结束标记
20 void Insert(char s[], int u)//u表示根节点
21 //插入字符串s
22 {
23     for(int i = 0; s[i]; i++)
24     {
25         int c = idx(s[i]);
26         if(!tree[u][c])
27             tree[u][c] = ++tot;
28         u = tree[u][c];
29     }
30     is_word [u] = true; //查询单词的时候需要标记最后一个节点的地方是单词
31 }
32 
33 bool Find(char s[], int u)
34 //查询s是否是前缀
35 {
36     for(int i = 0; s[i]; i++)
37     {
38         int c = idx(s[i]);
39         if(!tree[u][c])
40             return false;
41         u = tree[u][c];
42     }
43     //return true;
44     return is_word[u]; //查询单词的时候,需要返回当前是不是单词结束标志
45 }
46 char s[50005][20], s1[20];
47 int main()
48 {
49     int n = 0;
50     while(scanf("%s", s[n]) != EOF)Insert(s[n++], 1);
51 
52     for(int i = 0; i < n; i++)
53     {
54         for(int j = 1; s[i][j]; j++)//从下标1开始,从0开始的话s1就变成空串了
55         {
56             memcpy(s1, s[i], sizeof(s[i]));
57             s1[j] = 0;
58             //分割成两个字符串: s1和(s[i] + j)
59             //cout<<s1<<" "<<(s[i] + j)<<endl;
60             if(Find(s1, 1) && Find(s[i] + j, 1))
61             {
62                 cout<<s[i]<<endl;
63                 break;
64             }
65         }
66     }
67     return 0;
68 }

 

转载于:https://www.cnblogs.com/fzl194/p/8951003.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值