暴搜或者字典树,但是因为输出所有的方案而不是方案数,不管什么做法都逃不过输出,所以都差不多
sol1:记忆化搜索 当枚举方案时,f[i]表示已经把字符串的前i个字母都拼好的情况下有多少方案
考虑从第i+1个字符开始到j是一个给定的单词 如果有这样的j的话就可以转移
然后开一个vector把每一个状态下的方案存进去
sol2:字典树
对单词建trie树,每次碰到结束标记时就再回头走trie树,开一个队列记录方案
orz lz神仙爆搜90碾我标程
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
char s[205],c[205];
int cnt=1;
char tree[6050][27];
bool flag[6050];
int n;
char out[205];
int tot;
void build()
{
int now=1,len=strlen(c);
for(int i=0;i<len;i++)
{
int ch=c[i]-'a';
if(!tree[now][ch])
{
tree[now][ch]=++cnt;
}
now=tree[now][ch];
}
flag[now]=1;
}
void query(int noww)
{
int now=1,len=strlen(s),ch;
for(int i=noww;i<len;i++)
{
ch=s[i]-'a';
if(!tree[now][ch]) return;
now=tree[now][ch];
if(flag[now]==1)
{
for(int j=noww;j<=i;j++)
{
out[++tot]=s[j];
}
if(i!=len-1)
{
out[++tot]='_';
query(i+1);
tot--;
for(int j=noww;j<=i;j++) tot--;
}
else if(i==len-1)
{
for(int j=1;j<=tot;j++) putchar(out[j]);
printf("
");
for(int j=noww;j<=i;j++) tot--;
}
}
}
}
int main()
{
scanf("%s",s);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",c);
build();
}
query(0);
return 0;
}