<题目链接>
题目大意:
给定一个只有小写字母组成的目标串和m个模式串(里面可能有大写字母),记目标串反过来后的串为S,让你从m个模式串中选出若干个组成S串(不区分大小写)。输出任意一种方案。
解题分析:
将所有单词倒着建好Trie树后(字母忽略大小写),直接在Trie树上跑DFS,记录下所有符合条件的单词序号,然后输出即可。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int N =1e6+10; 7 const int M =1e5+10; 8 int n,m; 9 char s[M],word[M][1005]; 10 int trie[N][27],mark[N],ans[M],cnt,tot; 11 void Insert(char *str,int ord){ 12 int now=0,len=strlen(str); 13 for(int i=len-1;i>=0;i--){ //对这些单词进行逆序插入 14 int to; 15 if(str[i]>'Z')to=str[i]-'a'; //忽略单词的大小写 16 else to=str[i]-'A'; 17 if(!trie[now][to]) 18 trie[now][to]=++tot; 19 now=trie[now][to]; 20 } 21 mark[now]=ord; //记录下该单词的编号 22 } 23 bool dfs(int loc){ 24 if(s[loc]=='\0'){ //搜索结束 25 for(int i=0;i<cnt;i++){ 26 printf("%s%s",word[ans[i]],i==cnt-1?"\n":" "); 27 } 28 return true; 29 } 30 int now=0; 31 for(int i=loc;i<n;i++){ 32 int to=s[i]-'a'; 33 if(!trie[now][to])break; //如果不符合,说明这种搜索的情况不符,直接结束跳出 34 now=trie[now][to]; 35 if(mark[now]){ //如果搜到了单词库中完整的单词 36 ans[cnt++]=mark[now]; //记录下该单词的序号 37 if(dfs(i+1))return true; //继续向下搜索 38 cnt--; //如果之前的情况都不符合,这里进行回溯,继续对下一个字符进行搜索 39 } 40 } 41 return false; 42 } 43 int main(){ 44 tot=cnt=0; 45 scanf("%d%s",&n,s); 46 scanf("%d",&m); 47 for(int i=1;i<=m;i++){ 48 scanf("%s",word[i]); 49 Insert(word[i],i); 50 } 51 dfs(0); 52 return 0; 53 }
2018-11-03