用字典树,字典树存串,再将串由长度小到大排序,枚举将各个串否成两个子串,判断两个子串是否存在,最后按字典序排序结果串并输出。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e6 + 5;
int tot, trie[N][30];
bool flag[N];
struct abc{
char s[100];
}ss[50005];
struct cba{
char s[100];
}ans[50005];
void insert(char *str)
{
int len = strlen(str);
int root = 0;
for(int i = 0; i < len; ++i)
{
int id = str[i] - 'a';
if(!trie[root][id]) trie[root][id] = ++tot;
root = trie[root][id];
}
flag[root] = true;
}
bool find(char *str)
{
int len = strlen(str);
for(int i = 1; i < len; ++i)
{
int root = 0, ne = 1;
for(int j = 0; j < i; ++j){
int id = str[j] - 'a';
if(!trie[root][id]){
ne = 0;
break;
}
root = trie[root][id];
}
if(ne && flag[root]){
root = 0;
for(int j = i; j < len; ++j){
int id = str[j] - 'a';
if(!trie[root][id]){
ne = 0;
break;
}
root = trie[root][id];
}
if(ne && flag[root]){
return true;
}
}
}
return false;
}
bool cmp1(struct abc a, struct abc b){
if(strlen(a.s) < strlen(b.s)){
return true;
}
return false;
}
bool cmp2(struct cba a, struct cba b){
if(strcmp(a.s, b.s) < 0){
return true;
}
return false;
}
int main()
{
int cnt = 0, ans_cnt = 0;
while(scanf("%s", &ss[cnt].s) != EOF){
++cnt;
}
sort(ss, ss + cnt, cmp1);
for(int i = 0; i < cnt; ++i){
if(find(ss[i].s)){
strcpy(ans[ans_cnt].s, ss[i].s);
++ans_cnt;
}
insert(ss[i].s);
}
sort(ans, ans + ans_cnt, cmp2);
for(int i = 0; i < ans_cnt; ++i){
printf("%s\n", ans[i].s);
}
return 0;
}