给出多个单词组成单词表,问这些单词中有哪些可以拆成两个单词,并按字典序输出
按字典序输出自然要借助 set,对于每一个单词,我们将其正序放入字典树,再将其逆序放入字典树,这样存在两颗字典树
对于每一个单词将进行询问,如果可以由两个单词表示,那么一定存在位置 x,使得 1~x 为一个单词,x+1~len 为一个单词,只要找是否存在这样的 x 即可
const int N=5e4+5;
int n,m;
int i,j,k;
int t[N*50][26][2],tot[2]={0,0};
char s[N][55];
int vis[N*50][2],sum[50];
set<string> all;
int idx(char ch){ return ch-'a'; }
void insert(char *s,int id)
{
int rt=0;
for(int i=0;s[i];i++){
int x=idx(s[i]);
if(!t[rt][x][id]) t[rt][x][id]=++tot[id];
rt=t[rt][x][id];
}
vis[rt][id]=1;
}
void query(char *s,int id)
{
int rt=0;
int len=strlen(s);
for(int i=0;s[i];i++){
int x=idx(s[i]);
rt=t[rt][x][id];
if(vis[rt][id]){
if(id) sum[len-i-2]++;
else sum[i]++;
}
}
}
int main()
{
int cnt=0;
while(~ss(s[++cnt])){
insert(s[cnt],0);
insert(strrev(s[cnt]),1);
}
for(int i=1;i<=cnt;i++){
for(int j=0;j<50;j++) sum[j]=0;
query(s[i],1);
query(strrev(s[i]),0);
for(int j=0;j<50;j++) if(sum[j]==2) all.insert((string)s[i]);
}
for(set<string>::iterator it=all.begin();it!=all.end();it++) ps((*it).c_str());
}