您的位置:首页 > 其它

BZOJ3574 HNOI2014抄卡组(哈希)

2018-09-26 23:59 232 查看

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

  问题在于存在无通配符的字符串。显然首先这些字符串需要相同。剩下的字符串只要都能与该字符串匹配即可。然后就不会了。想了半天去看题解……暴力哈希。为啥跑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
,suf
,id
;
ul hash[2][L],p[L];
vector<char> s
;
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\n";
#else
const char LL[]="%lld\n";
#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\n";continue;}
if (!len)
{
if (!check(n)) {cout<<"N\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\n";continue;}
cout<<"Y\n";
}
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\n";else cout<<"Y\n";
}
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: