好久不写字典树,写道水题回忆一下,顺便刷刷题量 O(∩_∩)O哈哈~
题意:给你很多的单词,输出那些可以由其它的两个单词拼接起来的单词。
解法:先把所有单词插入到一个字典树中,然后暴力拆分每个单词,判断两段是不是都是单词,例如:abc 可以拆成 ab c和 a bc 分别判断是不是单词 如果两个都是单词就输出
Trick:题目中要求最后按照字典序输出,但是我没有这样写,直接按照输入顺序输出的,可能是数据太弱了吧。
#include <iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define pi acos(-1.0)
#define eps 1e-8
using namespace std;
const int maxnode = 500010;
const int char_size = 27;
struct trie
{
int ch[maxnode][char_size], val[maxnode];
int sz;
int idx(char c){return c- 'a';}
void init(){sz = 1;memset(ch[0],0,sizeof ch[0]);}
void insert(char* s, int v = 1)
{
int u = 0, 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 a;
a = 1;
}
bool find(char* s)
{
int u = 0, n = strlen(s);
for(int i = 0 ; i < n ; ++ i)
{
int c = idx(s[i]);
if(!ch[u][c])
{
return false;
}
u = ch[u][c];
}
if(val[u]) return true;
return false;
}
}tr;
char s[50000][110];
int main()
{
//freopen("in.txt","r",stdin);
int n = 0;
tr.init();
while(~scanf("%s", s+(n++)))
{
int i = n - 1;
tr.insert(s[i]);
}
for(int i = 0 ; i < n ; ++ i)
{
for(int j = 1; j < strlen(s[i]) ; ++ j )
{
char temp1[100], temp2[100];
memset(temp1,0,sizeof temp1);
memset(temp2,0,sizeof temp2);
strncpy(temp1,s[i],j);
strncpy(temp2,s[i]+j,strlen(s[i])-j);
if(tr.find(temp1)&&tr.find(temp2))
{
printf("%s\n",s[i]);
break;
}
}
}
return 0;
}