题目链接:
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 }