Codeforces 633C Spy Syndrome 2 【Trie树】+【DFS】

<题目链接>

题目大意:
给定一个只有小写字母组成的目标串和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]==''){    //搜索结束
25         for(int i=0;i<cnt;i++){
26             printf("%s%s",word[ans[i]],i==cnt-1?"
":" ");
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

原文地址:https://www.cnblogs.com/00isok/p/9901253.html