字典树(+DFS)——Watto and Mechanism ( CodeForces 514C )

  • 题目链接:
    http://codeforces.com/contest/514/problem/C

  • 分析:
    题目是先给出n个字符串和m个字符串,对于m个字符串中每一个字符串都可以在n个字符串中找到一个与之匹配(允许由一位字符的差异,但不允许超出或少于)。一看题目,就能想到是用n 个字符串建树,然后再搜索。

  • 题解:
    比较难写的是这个DFS函数,先讨论字符串有没有到底,到底后无错误并且之后没有节点了,就返回true,否则返回false;
    然后讨论下一个字符对应的节点有没有值,有则递归判断。
    最后,如果再某一个递归处发现一个错误,那么继续递归判断,然后返回结果。

  • DFS函数:

bool dfs(Trie *tr,int len,int f)
{
        if(s[len]=='\0' )//字符串到底了
        {
            if(f==0 && tr->index==1)  //如果无错误且之后无节点
                return true;
            else
                return false;
        }
        if(tr->next[s[len]-'a']!=0)//字符串未到底,并且字典树之后还有节点
        {
            if(dfs(tr->next[s[len]-'a'],len+1,f))//递归调用
                return true;
        }
        if(f==1)//如果字符串未到底,但是字典树到底了或者不匹配并且诶错误为1,就递归调用
        {
            int i;
            for(i=0;i<=2;i++)
                if(i!=s[len]-'a' && tr->next[i]!=0)
                    if(dfs(tr->next[i],len+1,0))
                        return true;
        }
        return false;
}
  • 代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
int T,t,n,m;
char s[1000010];
struct Trie
{
        int index;
        Trie *next[3];
        Trie()
        {
            index=-1;
            memset(next,0,sizeof(next));
        }
};
Trie *root=new Trie;
void Trie_Insert(Trie *tr,int len)
{
        if(s[len]!='\0')
        {
            if(tr->next[s[len]-'a']==0)
                tr->next[s[len]-'a']=new Trie;
            Trie_Insert(tr->next[s[len]-'a'],len+1);
        }
        else
            tr->index=1;   //表示这之后没有节点
}
bool dfs(Trie *tr,int len,int f)
{
        if(s[len]=='\0' )
        {
            if(f==0 && tr->index==1)  //如果无错误且之后无节点
                return true;
            else
                return false;
        }
        if(tr->next[s[len]-'a']!=0)
        {
            if(dfs(tr->next[s[len]-'a'],len+1,f))
                return true;
        }
        if(f==1)
        {
            int i;
            for(i=0;i<=2;i++)
                if(i!=s[len]-'a' && tr->next[i]!=0)
                    if(dfs(tr->next[i],len+1,0))
                        return true;
        }
        return false;
}
int main()
{
        int i,j,k;
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)
        {
            scanf("%s",s+1);
            Trie_Insert(root,1);
        }
        for(i=1;i<=m;i++)
        {
            scanf("%s",s+1);
            if(dfs(root,1,1))
                printf("YES\n");
            else
                printf("NO\n");
        }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值