您的位置:首页 > 其它

C. Watto and Mechanism

2015-07-25 21:15 274 查看
time limit per test3 secondsmemory limit per test256 megabytesinputstandard inputoutputstandard outputWatto, the owner of a spare parts store, has recently got an order for the mechanism that can process strings in a certain way. Initially the memory of the mechanism is filled withnstrings. Then the mechanism should be able to process queries of the following type: "Given strings, determine if the memory of the mechanism contains stringt that consists of the same numberof characters ass and differs froms in exactly one position".Watto has already compiled the mechanism, all that's left is to write a program for it and check it on the data consisting ofn initial lines andm queries. He decided to entrust this job to you.InputThe first line contains two non-negative numbersn and m (0 ≤ n ≤ 3·105,0 ≤ m ≤ 3·105) — the number of the initial stringsand the number of queries, respectively.Next follow n non-empty strings that are uploaded to the memory of the mechanism.Next follow m non-empty strings that are the queries to the mechanism.The total length of lines in the input doesn't exceed6·105. Each line consistsonly of letters 'a','b', 'c'.OutputFor each query print on a single line "YES" (without the quotes), if the memory of the mechanism contains the required string, otherwise print "NO" (without thequotes).Sample test(s)Input
2 3
aaaaa
acacaca
aabaa
ccacacc
caaac
Output
YES
NO
NO

题意:输入n+m串字符串,判断m中的每个字符串是否在前n个字符串中有满足条件(1.长度相同;2.最多只有一个字符不一样)的对应字符串;
分析:字典树+dfs  据说暴力也能过;
#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;

const int MAXN=1000010; //其实300000以上就够 习惯开大些
int dic[MAXN][5],val[MAXN],cnt,flag,ok;

void inst(char *s)  //插入Trie树 数组为链
{
int u=0,v,len;
len=strlen(s);
for(int i=0;i<len;i++)
{
v=s[i]-'a'+1;   //分别标记 a b c 为 1 2 3  其实0 1 2 也可以 不过为了与初始化的值区分开 便于查错 就这样做了
if(!dic[u][v])   //如果此节点未被编码过
{
dic[u][v]=++cnt;  //编码此数组 其实就是形成链表的过程
memset(dic[cnt],0,sizeof(dic[cnt]));  //初始化该节点下所属的字母
}
u=dic[u][v];   //取出该节点编码 作用:1、便于对该节点赋值操作 2、生成链表或继续访问链表
if(i==len-1) val[u]=1;  //如果此时该字符串已结束 标记结束时的编码值
}
}

bool dfs(char  *s,int r,int u,int num) //括号里面的内容分别为  字符串s 字符下标r 字符的节点u 不同字母个数num
{
if(s[r]) //如果该字符串没有结束
{
int v=s[r]-'a'+1;  // a b c 转换为 1 2 3 与插入时保持一致
if(dic[u][v])   //如果该字母与树上的字母有匹配的连接方式
{
if(dfs(s,r+1,dic[u][v],num)) {return true;}  //继续深搜 一直到底 如果中途不满足条件就会跳出
}
if(!num)   //num最多有1个 只有为0的时候才可替换此处字母继续访问链标
{
for(int i=1;i<=3;i++)
{
if(i!=v&&dic[u][i])   //与原来字母不相同 并且树上存在匹配方式
if(dfs(s,r+1,dic[u][i],num+1))   //相当与把当前字母替换为其他字母 然后继续访问
return true;
}
}
}
else if(num&&val[u]) return true;  //字符串已结束 判断是否有同样长度的字符串
return false;
}

int main()
{
int n,m;
char s[MAXN];   //这里如果用string会暴MEMORY  这里不大明白为什么 谅

memset(dic[0],0,sizeof(dic[0]));  //一次性全部初始化也可
memset(val,0,sizeof(val));    //初始化所有编码值
cnt=0;    //初始化编码号

scanf("%d%d",&n,&m);
getchar();
for(int i=0;i<n;i++)  //插入字符操作 一开始考虑用set去存字符串 结果查看测试数据时发现其实没必要
{
scanf("%s",s);
inst(s);
}

for(int i=0;i<m;i++)
{
scanf("%s",&s);
flag=dfs(s,0,0,0);   //flag标记该串是否满足条件
if(flag) printf("YES\n");
else printf("NO\n");
}
}

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: