// hdu 1247 Hat’s Words 字典树 // // 题目大意: // // 在一些字符串中,找到这样字符串:由两个其它的字符串构成 // // 解题思路: // // 字典树,先将这些字符串插入到字典树中,然后枚举断点,假设 // 字符串的前后两段都找到了。输出该串就可以~ // // 感悟: // // 这道题目的话,就是字典树上的暴力嘛。细节方面还是要多多注意 // val值还是不能少哟~由于查找到了该串,不一定是一个单词,可能 // 是中间的一个节点,即某个字符串的前缀~~~FIGHTING! #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int MAX_N = 400000; char s[50005][100]; struct Trie{ int ch[MAX_N][26]; int val[MAX_N]; int sz; void init(){ memset(ch[0],0,sizeof(ch[0])); sz = 1; val[0] = 0; } int idx(char c){ return c - 'a'; } void insert(char *s,int v){ int u = 0; int n = strlen(s); for (int i=0;i<n;i++){ int c = idx(s[i]); if (!ch[u][c]){ memset(ch[sz],0,sizeof(ch[sz])); val[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; } val[u] = v; } int query(char *s,int st,int ed){ int u = 0; //int n = strlen(s); for (int i=st;i<ed;i++){ int c = idx(s[i]); if (!ch[u][c]) return 0; u = ch[u][c]; } return val[u]; } }trie; int main(){ //freopen("1.txt","r",stdin); int cnt = 1; char x[100]; trie.init(); while(scanf("%s",x)!=EOF){ memcpy(s[cnt],x,sizeof(x)); trie.insert(x,cnt); cnt++; } for (int i = 1;i < cnt;i++){ int n = strlen(s[i]); for (int j = 1;j < n;j++) if (trie.query(s[i],0,j) && trie.query(s[i],j,n)){ printf("%s ",s[i]); break; } } return 0; }