题目链接: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;
}