Codeforces 514C Watto and Mechanism 【Trie树】+【DFS】

<题目链接>

题目大意:
输入n个单词构成单词库,然后进行m次查询,每次查询输入一个单词(注意这些单词只由a,b,c构成),问该单词库中是否存在与当前查询的单词有且仅有一个字符不同的单词。

解题分析:
本题将单词库中所有的单词先建trie树,然后进行容错数为1的字符串匹配,主要是在trie树上跑DFS,具体步骤见代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 const int M = 6e5+100;
 7 typedef long long ll;
 8 int n,m;
 9 char s[M];
10 struct Trie{
11     int cur;
12     Trie *next[3];
13     Trie(){
14         cur=-1;
15         for(int i=0;i<=2;i++)
16             next[i]=NULL;
17     }
18 };
19 Trie *root=new Trie;
20 /*void Insert(){       //为什么这种建树方式会超时,而下面的递归建树不会?
21     Trie *now=root;
22     for(int i=0;i<strlen(s);i++){
23         int to=s[i]-'a';
24         if(now->next[to]==0)
25             now->next[to]=new Trie;
26         now=now->next[to];
27     }
28     now->cur=1;
29 }*/
30 void Trie_Insert(Trie *now,int loc){    //递归进行Trie树的构建
31     if(s[loc]!='\0'){
32         int to=s[loc]-'a';
33         if(now->next[to]==NULL)
34             now->next[to]=new Trie;
35         Trie_Insert(now->next[to],loc+1);
36     }
37     else now->cur=1;
38 }
39 bool dfs(Trie *now,int loc,int num){    //now代表当前Trie树上的节点,loc为当前遍历到的字符串上的字符下标,num代表容错数
40     if(s[loc]=='\0'){
41         if(num==0&&now->cur==1)return true;     //如果在该字符串结束时有且仅有一处错误,则符合条件
42         else return false;
43     }
44     int to=s[loc]-'a';
45     if(now->next[to]!=NULL){    //1.当前字符与Trie树匹配的情况,只有该字符与当前节点相等,才能继续向下dfs
46         if(dfs(now->next[to],loc+1,num))
47             return true;
48     }
49     if(num==1){     //2.当前loc处的字符为错误字符时,进行容错处理
50         for(int i=0;i<=2;i++){
51             if(i!=s[loc]-'a'&&now->next[i]!=NULL)   //枚举该节点的子节点a,b,c三种三种字符的不同情况,从中挑选与当前字符不同的情况,继续向下匹配
52                 if(dfs(now->next[i],loc+1,0))   //由于当前loc位置为错误字符,所以下面的字符容错数为0
53                     return true;
54         }
55     }
56     return false;
57 }
58 int main(){
59     scanf("%d%d",&n,&m);
60     for(int i=1;i<=n;i++){
61         scanf("%s",s);
62         //Insert();
63         Trie_Insert(root,0);
64     }
65     for(int i=1;i<=m;i++){
66         scanf("%s",s);
67         if(dfs(root,0,1))
68             printf("YES\n");
69         else printf("NO\n");
70     }
71     return 0;
72 }

 

 

2018-11-01

转载于:https://www.cnblogs.com/00isok/p/9892221.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值