题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1247
分析:这道题可以使用stl中的map直接来解决,也可以使用字典树来解决,当然字典树的效率会更高
(1)stl解法不做过多的解释,这里有网上一个stl解法的链接 http://hi.baidu.com/mingyiyiyi_3/item/25835459866641494eff20f5
(2)字典树解法,字典树 (详细看链接解释)
定义一个字典树结构体
typedef struct Trie { bool flag;//从根到此是否为一个单词 Trie *next[MAXNUM]; }Trie;
字典树的插入操作
void insert(char *word) { Trie *tem = root; while(*word!='\0') { if(tem->next[*word-'a']==NULL) { Trie *cur = (Trie *)malloc(sizeof(Trie)); for(int i=0;i<MAXNUM;i++) cur->next[i]=NULL; cur->flag=false; tem->next[*word-'a']=cur; } tem = tem->next[*word-'a']; word++; } tem->flag=true; }
以上两段代码是字典树的核心,要先弄懂。然后针对本题,flag是标志从根到当前位置是否可以组成一个单词,是为true,否为false。然后搜索每个单词是否有两个单词组成,这时就要把每个单词拆分,一个长度为n的单词可以拆分为n-1组组合,然后枚举判断是否在该字典树集合内。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define MAXNUM 26 using namespace std; //单词 char words[50005][100]; //定义字典树 typedef struct Trie { bool flag;//从根到此是否为一个单词 Trie *next[MAXNUM]; }Trie; Trie *root; void init() { root = (Trie *)malloc(sizeof(Trie)); root->flag=false; for(int i=0;i<MAXNUM;i++) root->next[i]=NULL; } void insert(char *word) { Trie *tem = root; while(*word!='\0') { if(tem->next[*word-'a']==NULL) { Trie *cur = (Trie *)malloc(sizeof(Trie)); for(int i=0;i<MAXNUM;i++) cur->next[i]=NULL; cur->flag=false; tem->next[*word-'a']=cur; } tem = tem->next[*word-'a']; word++; } tem->flag=true; } bool search(char *word) { Trie *tem = root; for(int i=0;word[i]!='\0';i++) { if(tem==NULL||tem->next[word[i]-'a']==NULL) return false; tem=tem->next[word[i]-'a']; } return tem->flag; } int main() { init(); int t=0; char w[100]; while(scanf("%s",words[t])!=EOF) { insert(words[t]); t++; } for(int i=0;i<t;i++) { memset(w,'\0',sizeof(w)); for(int j=0;words[i][j]!='\0';j++) { *(w+j)=*(words[i]+j); if(search(w)&&search((words[i]+j+1))) { printf("%s\n",words[i]); break; } } } return 0; }