• BZOJ3574 HNOI2014抄卡组(哈希)


      容易发现通配符中间的部分可以任意匹配,会造成的无法匹配的仅仅是前后缀,前缀和后缀可以分别独立处理。如果字符串均有通配符,只需要按前/后缀长度排序然后暴力匹配就可以了。

      问题在于存在无通配符的字符串。显然首先这些字符串需要相同。剩下的字符串只要都能与该字符串匹配即可。然后就不会了。想了半天去看题解……暴力哈希。为啥跑2e8这么自信啊。

      bzoj莫名T。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 100010
    #define L 10000010
    #define ul unsigned long long
    int T,n,pre[N],suf[N],id[N];
    ul hash[2][L],p[L];
    vector<char> s[N];
    bool isac(char c){return c>='a'&&c<='z'||c>='0'&&c<='9'||c=='*';}
    bool cmp(const int&a,const int&b)
    {
        return pre[a]<pre[b];
    }
    bool check(int n)
    {
        for (int i=1;i<=n;i++) id[i]=i;
        sort(id+1,id+n+1,cmp);
        for (int i=2;i<=n;i++)
            for (int j=0;j<pre[id[i-1]];j++)
            if (s[id[i-1]][j]!=s[id[i]][j]) return 0;
        return 1;
    }
    ul gethash(int k,int l,int r)
    {
        if (l>r) return 0;
        return hash[k][r]-hash[k][l-1]*p[r-l+1];
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj3574.in","r",stdin);
        freopen("bzoj3574.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        T=read();
        p[0]=1;for (int i=1;i<=L-10;i++) p[i]=p[i-1]*509;
        while (T--)
        {
            n=read();
            for (int i=1;i<=n;i++)
            {
                s[i].clear();
                char c=getchar();while (!isac(c)) c=getchar();
                while (isac(c)) s[i].push_back(c),c=getchar();
            }
            hash[0][0]=0;int len=0;bool flag=1;
            for (int i=1;i<=n;i++)
            {
                int l=s[i].size();
                pre[i]=l,suf[i]=-1;
                for (int j=0;j<l;j++)
                if (s[i][j]=='*') {pre[i]=j;break;}
                for (int j=l-1;~j;j--)
                if (s[i][j]=='*') {suf[i]=j;break;}
                if (pre[i]==l)
                if (!len)
                {
                    len=l;
                    for (int j=0;j<l;j++) hash[0][j+1]=hash[0][j]*509+s[i][j];
                }
                else
                {
                    ul tot=0;
                    for (int j=0;j<l;j++) tot=tot*509+s[i][j];
                    if (tot!=hash[0][len]) {flag=0;break;}
                }
            }
            if (!flag) {cout<<"N
    ";continue;}
            if (!len)
            {
                if (!check(n)) {cout<<"N
    ";continue;}
                for (int i=1;i<=n;i++)
                {
                    reverse(s[i].begin(),s[i].end());
                    pre[i]=(int)s[i].size()-suf[i]-1;
                }
                if (!check(n)) {cout<<"N
    ";continue;}
                cout<<"Y
    ";
            }
            else
            {
                bool flag=0;
                for (int i=1;i<=n;i++)
                if (pre[i]!=s[i].size())
                {
                    hash[1][0]=0;
                    int l=s[i].size();
                    for (int j=0;j<l;j++) hash[1][j+1]=hash[1][j]*509+s[i][j];
                    if (pre[i]+l-1-suf[i]>len||gethash(0,1,pre[i])!=gethash(1,1,pre[i])||gethash(0,len-l+suf[i]+2,len)!=gethash(1,suf[i]+2,l)) {flag=1;break;}
                    int x=pre[i]+1;flag=1;
                    for (int j=pre[i];j<=suf[i];j++)
                    {
                        if (j==suf[i]) flag=0;
                        if (s[i][j]=='*') continue;
                        int t=j;
                        while (s[i][t+1]!='*') t++;
                        while (x+t-j<len-l+suf[i]+2&&gethash(0,x,x+t-j)!=gethash(1,j+1,t+1)) x++;
                        if (x+t-j>=len-l+suf[i]+2) break;
                        j=t;
                    }
                    if (flag) break; 
                }
                if (flag) cout<<"N
    ";else cout<<"Y
    ";
            }
        }
        return 0;
    }
  • 相关阅读:
    封装一个php语言的api提示类
    Content-Type四种常见取值
    postman中 form-data、x-www-form-urlencoded、raw、binary的区别
    ansible find
    Linux系统中根目录下或者新挂载的磁盘目录下有一个叫lost+found,它的作用是什么?
    rm /mv需要注意的
    mount
    es number_of_shards和number_of_replicas
    logstash设置配置路径
    ES7.8 设置 xpack
  • 原文地址:https://www.cnblogs.com/Gloid/p/9710851.html
Copyright © 2020-2023  润新知