zoukankan      html  css  js  c++  java
  • 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;
    }

                                                                                                                                                                 

  • 相关阅读:
    助教小结4
    第二次作业
    助教小结5
    助教小结3
    work3
    助教小结1
    课后第一次作业
    助教小结2
    第一次团队作业
    悟透 JavaScript
  • 原文地址:https://www.cnblogs.com/zhyfzy/p/4293041.html
Copyright © 2011-2022 走看看