题意:原本有一个串有许多单词,中间用空格隔开,后来把单词全部转换成小写,然后翻转,再把中间的所有的空格全部去掉,就得到了一个全是小写字母组成的串。
现在告诉你这样的串,并告诉你字典,要你找出一种满足条件的原串,保证有解。
思路:字典逆序插入到Trie中 在原串上暴力匹配并记录每次匹配的单词输出即可
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N=1e6+20;
const int M=1e5+20;
int n,m;
char a[M];//
char s[M][1010];//
//end[i] 结点i是否为某个sub[x]的最后一个字符
int next[N][30],end[N];//trie
int root,num;//
int tot=0,ans[M],len[N];
void insert(int x)
{
int u=0,l=len[x];
for(int i=l-1;i>=0;i--)//反向插入
{
int id;
char t=s[x][i];
if(t>='A'&&t<='Z')
id=t-'A';
else
id=t-'a';
if(!next[u][id])
next[u][id]=++num;//
u=next[u][id];//
}
// cout<<u<<endl;
end[u]=x;//
}
void dfs(int pos)
{
if(pos==n)
{
for(int i=1;i<=tot;i++)
{
printf("%s",s[ans[i]]);
if(i==tot)
printf("\n");
else
printf(" ");
}
exit(0);
}
int u=root;//按字典暴力匹配
for(int i=pos+1;i<=n;i++)
{
int id=a[i]-'a';
u=next[u][id];
if(!u)
break;
// cout<<end[u]<<" "<<u<<endl;
if(end[u]!=-1)
{
ans[++tot]=end[u];
dfs(pos+len[end[u]]);//跳到该单词结尾继续匹配
tot--;//回溯
}
}
}
int main()
{
memset(next,0,sizeof(next));
memset(end,-1,sizeof(end));
root=0;
cin>>n;
scanf("%s",a+1);
cin>>m;
for(int i=0;i<m;i++)
{
scanf("%s",s[i]);
len[i]=strlen(s[i]);
insert(i);//
}
dfs(0);
return 0;
}