这题目没说字符串长度和是多少...也没说每个单词最长多长...当成最长20然后过的..
开两个字典树,一个是给出的串构成的,一个是给出的串的逆串构成的,然后对于每个有的单词,看一下他的后缀都有多长的,然后看一下能不能加到他的长度
复杂度O(n),n为总长度
#include <cstdio>
#include <cstring>
using namespace std;
struct Node {
Node *s[26];
bool match;
};
bool e[20]={0},f[20];
struct TrieTree {
Node a[1000000];
int p;
Node *root;
Node *newNode() {
memset(a[p].s,0,sizeof(a[p].s));
a[p].match=false;
return &a[p++];
}
TrieTree() {
p=0;
root=newNode();
}
void insert(char *s) {
Node *cur=root;
while (*s!='\0') {
int t=*(s++)-'a';
if (cur->s[t]==NULL) cur->s[t]=newNode();
cur=cur->s[t];
}
cur->match=true;
}
void check(char *s) {
int l=0;
Node *cur=root;
while (*s!='\0') {
int t=*(s++)-'a';
if (cur->s[t]==NULL) return;
cur=cur->s[t];
l++;
if (cur->match) f[l]=true;
}
}
};
TrieTree a,b;
char s1[20];
char s2[20];
int ls;
void gets2() {
ls=strlen(s1);
for (int i=0;i<ls;i++) s2[i]=s1[ls-i-1];
s2[ls]='\0';
}
bool check() {
memset(f,0,sizeof(f));
b.check(s2);
for (int i=1;i<ls;i++) {
if (e[i]&&f[ls-i]) return true;
}
return false;
}
void dfs(Node *from,int i) {
if (from->match) {
s1[i]='\0';
gets2();
if (check()) printf("%s\n",s1);
e[i]=true;
}
for (int j=0;j<26;j++) {
if (from->s[j]) {
s1[i]=j+'a';
dfs(from->s[j],i+1);
}
}
e[i]=false;
}
int main() {
int i;
while (scanf("%s",s1)!=EOF) {
gets2();
a.insert(s1);
b.insert(s2);
}
dfs(a.root,0);
return 0;
}