C. Watto and Mechanism 字典树+dfs

时间:2022-12-30 13:12:36

题目链接:C. Watto and Mechanism

题目大意:

给出n个字符串 和k此查询,每次查询的字符串,问是否在给出的n个字符串中找到和查询的字符串有且只有一位不同的字符串,找到输出YES,找不到输出NO;

题解:刚刚看到除了暴力别无想法,看了别人的题解说是要用到trie树,就学习了一下trie树,这个大牛讲的不错字典树入门。这题就是用字典树建树后,使用dfs深搜素就能搞定了。

注意点:这题dfs路径一定要搜全,dfs题目逻辑一定要清楚全面啊!wa了好几次了。

#include<iostream>
#include<string>
#include<cstring>
using namespace std;
const int maxn = 300010;
int trie[maxn][26], n, k, tot, rt, vis[maxn];
char s[10000];
bool flag;
void insert()
{
    rt = 0;
    int len = strlen(s);
    for (int i = 0; i < len; ++i)
    {
        int id = s[i] - 'a';
        if (trie[rt][id] == 0)trie[rt][id] = ++tot;
        rt = trie[rt][id];
    }
    vis[rt] = 1; //字符串插入结束
}
bool dfs(int pos, int u, int num)//当前搜素到字符串的第pos位 节点u 不同个数num
{
    if (s[pos]) //字符串还没有结束
    {
        int id = s[pos] - 'a';

        //当前路径正确一直搜素下去
        if (trie[u][id])
        {
            if (dfs(pos + 1, trie[u][id], num))return true;
        }

        //如果还没有出现不同的 可以查看改节点下的子节点是否有其他字母,继续往下搜素
         if (!num)
        {
            for (int i = 0; i < 3; ++i)
            {
                if (trie[u][i]&&i!=id)
                    if (dfs(pos + 1, trie[u][i], num + 1))return true;
            }
        }
    }
    else if (vis[u]&&num==1)return true;

    //所有路径都不对才返回false 只要有一条是正确的 上面都会返回ture
    return false;
}
int main()
{
    cin >> n;
    cin >> k;
    for (int i = 1; i <= n; ++i)
    {
        cin >> s;
        insert();
    }

    for (int i = 1; i <= k; ++i)
    {
        cin >> s;
        flag = dfs(0, 0, 0);
        if (flag)cout << "YES" << endl;
        else cout << "NO"<<endl;
    }
    return 0;
}