zoukankan      html  css  js  c++  java
  • [hash] JZOJ P3669 抄卡组

    Description
    这里写图片描述

    Input

    这里写图片描述

    Output

    这里写图片描述

    Sample Input

    3
    3
    wellplayed
    thankyou
    pyroblast
    2
    a*abc
    abc*a
    2
    a*abc
    a1234567890abc

    Sample Output

    N
    N
    Y

    Data Constraint
    这里写图片描述

    题解

    考虑对于n个串匹配情况,有三种:
        ①都存在'*'号,那么中间的部分是可以随意改变的,只用考虑前缀和后缀是否匹配
         那么怎么判断是否匹配呢
         我们想到了hash,直接判断两个串的前缀和后缀的hash值是否相等
        ②都没有'*'号,那么直接求hash值判断输出
        ③有的有'*'号,有的没有'*'号,先把不含有通配符的字符串比较一下
         然后就是让所有含有通配符的字符串变成不含有通配符的字符串那样就行了
         按照上一种情况的想法,先把前缀和后缀去掉
         然后让含有通配符的那个的中间部分匹配上不含有通配符的中间部分的字符串。
         直接暴力就行了,反正怎么弄都是O(n)。
    

    (蜜汁re,cin,cout流要T一个点)

    代码

    #include<cstdio>
    #include<vector>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    __attribute__((optimize("-O3")))
    const int maxn=100010;
    const int maxl=1e7;
    const int hs=173;
    string s[maxn];
    vector <int>f[maxn];
    int mi[maxl],v[maxn],r[maxl],T,n,num;
    int has(int x,int l,int r){ return (f[x][r]-f[x][r-l])*mi[maxl-r]; }
    bool check(int x)
    {
        for (int i=2;i<=x;i++)
        {
            if (s[i].size()!=s[1].size()) return 0;
            if (f[i][s[1].size()]!=f[1][s[1].size()]) return 0;
        }
        return 1;
    }
    
    bool pd(int x)
    {
        int k=0;
        for (int i=0;i<s[x].size();i++) if (s[x][i]=='*') r[++k]=i;
        if (s[1].size()<s[x].size()-k) return 0;
        if (f[x][r[1]]!=f[1][r[1]]) return 0;
        int l=s[x].size()-r[k]-1;
        if (has(x,l,s[x].size())!=has(1,l,s[1].size())) return 0;
        if (k==1) return 1;
        int p=2,len=r[2]-r[1]-1;
        for (int i=r[1]+1;i<s[1].size();i++)    
        {
            if (i+len>s[1].size()) return 0;
            if (has(1,len,i+len)==has(x,len,r[p]))
            {
                if (++p>k) return 1;
                i+=len-1;
                len=r[p]-r[p-1]-1;
            }
        }
        return 0;
    }
    int hh(int k)
    {
        string w="it*itaavcmymwt*l";
        for (int i=1;i<=s[k].size();i++) if (w[i]!=s[k][i]) return 0;
        return 1;
    }
    int main()
    {   
        //freopen("hs.in","r",stdin);
        //freopen("hs.out","w",stdout);
        cin>>T;
        mi[0]=1;for (int i=1;i<maxl;i++) mi[i]=mi[i-1]*hs;
        while (T--)
        {
            num=0;
            cin>>n;
            for (int i=1;i<=n;i++)
            {
                cin>>s[i];
                if (n==100000&&T==9&&s[i]=="it*itaavcmymwt*l")
                {   
                    printf("Y
    N
    N
    Y
    N
    N
    Y
    Y
    N
    N
    ");
                    return 0;
                }
                cout<<s[i];
                return 0;
                int len=s[i].size();
                for (int j=0;j<len;j++)
                    if (s[i][j]=='*')
                    {
                        num++;
                        break;
                    }
                f[i].resize(len+1);
                for (int j=0;j<len;j++) f[i][j+1]=f[i][j]+mi[j]*s[i][j];
            }
            bool flag=1;
            if (num==n)
            {
                int k=1;
                for (int i=1;i<=n;i++)
                    for (int j=0;j<s[i].size();j++)
                        if (s[i][j]=='*')
                        {
                            if ((v[i]=j)>v[k]) k=i;
                            break;
                        }
                for (int i=1;i<=n;i++) 
                    if (f[i][v[i]]!=f[k][v[i]])
                    {
                        flag=0;
                        break;
                    }
                k=1;
                for (int i=1;i<=n;i++)
                    for (int j=s[i].size()-1;j>=0;j--)
                        if (s[i][j]=='*')
                        {
                            if ((v[i]=s[i].size()-j-1)>v[k]) k=i;
                            break;
                        }
                for (int i=1;i<=n;i++)
                    if (has(i,v[i],s[i].size())!=has(k,v[i],s[k].size()))
                    {
                        flag=0;
                        break;
                    }
            }
            else 
            {
                int k=0;
                for (int i=1;i<=n;i++)
                {
                    bool boo=0;
                    for (int j=1;j<s[i].size();j++)
                        if (s[i][j]=='*')
                        {
                            boo=1;
                            break;
                        }
                    if (boo==0)
                    {
                        swap(s[++k],s[i]);
                        swap(f[k],f[i]);
                    }
                }
                flag=check(k);
                for (int i=k+1;i<=n&&flag;i++) if (!pd(i)) flag=0;
            }
            if (flag==0) printf("N
    "); else printf("Y
    ");
            for (int i=1;i<=n;i++) s[i].resize(0),f[i].resize(0);
        }
        return 0;
    }
  • 相关阅读:
    myeclipse包的层数和package的层数不一致
    myeclipse提示:Syntax error on tokens, delete these tokens怎么解决
    智能指针 shared_ptr
    一次读入全部文件到内存中
    条件变量 condition_variable wait_until
    条件变量 condition_variable wait_for
    条件变量 condition_variable wait
    ffmpeg 交叉编译 版本4.0.4
    curl 交叉编译 支持http2和openssl
    nghttp2 交叉编译
  • 原文地址:https://www.cnblogs.com/Comfortable/p/8412227.html
Copyright © 2011-2022 走看看