Codeforces Round #291 (Div. 2) C

【题意】给n个字符串组成的集合,然后有m个询问(0 ≤ n ≤ 3·105, 0 ≤ m ≤ 3·105) ,每个询问都给出一个字符串s,问集合中是否存在一个字符串t,使得s和t长度相同,并且仅有一个字符不同。(字符串总长度为6·105),所有字符只有a,b,c。

【题解】因为只有三种字符,用Trie最合适。先把n个字符串插入到Trie中。然后每读入一个字符串,首先枚举差异字符的位置,依次替换为另外两种字符,并检查是否合法。如果合法就直接输出YES。

显然每替换一个字符就从头检查一遍太浪费时间,所以保存字典树中差异字符位置的指针,每次从该位置开始检查即可。

我一开始是直接处理n个字符串,枚举差异字符的位置,分别替换后加入到字典树中。但是这样做会耗费相当多的空间,空间复杂度是指数级别(3^len)。MLE或者RE。但是一直返回的是WA7,QAQ找了半天错。。

还有一种方法时使用字符串哈希,但是如果运气不好的话,会出现冲突,然后WA掉,这次比赛很多人跪在了这里

#include<bits/stdc++.h>
#define eps 1e-9
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define MAXN 1000005
#define MAXM 40005
#define INF 0x3fffffff
using namespace std;
typedef long long LL;
int i,j,k,n,m,x,y,T,ans,big,cas,num,len;
bool flag;
char s[1000005];

struct Trie
{
    int ch[1000005][26];
    int val[1000005];
    int size;
    Trie()
    {
        size=1;
        memset(ch[0],0,sizeof(ch[0]));
        val[0]=0;
        val[1]=0;
    }
     
    int idx(char c)
    {
        return c-'a';
    }
     
    void insert(char *s,int v)
    {
        int u=0,len=strlen(s);
        for (int i=0;i<len;i++)
        {
            int c=idx(s[i]);
            if (!ch[u][c])
            {
                memset(ch[size],0,sizeof(ch[size]));
                val[size]=0;
                ch[u][c]=size++;
            }
            u=ch[u][c];
        }
        val[u]=v;
    }
    
    bool exist(char *s)
    {
        int u=0,len=strlen(s);
        for (int i=0;i<len;i++)
        {
            int c=idx(s[i]);
            
            for (int j=0;j<3;j++)
            {
                if (c==j || ch[u][j]==0) continue;
                int u2=ch[u][j];
                flag=true;
                for (int k=i+1;k<len;k++)
                {
                    int c=idx(s[k]);
                    if (!ch[u2][c]) 
                    {
                        flag=false;
                        break;
                    }
                    u2=ch[u2][c];
                }
                if (flag && val[u2]) 
                {
                    return true;
                }
            }
            
            if (!ch[u][c])
            {
                return false;
            }
            u=ch[u][c];
        }
        return false;
    }
} tree;

int main()
{
    scanf("%d%d",&n,&m);
    for (i=1;i<=n;i++)
    {
        scanf("%s",s);
        tree.insert(s,1);
    }
    for (i=1;i<=m;i++)
    {
        scanf("%s",s);
        if (tree.exist(s)) puts("YES");
        else puts("NO");
    }
        
    return 0;
}

                                                                                                                                                             

原文地址:https://www.cnblogs.com/zhyfzy/p/4293041.html