Codeforces Round #291 (Div. 2) C - Watto and Mechanism 字符串

【题意】给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;

}

 

                                                                                                                                                             

你可能感兴趣的:(codeforces)