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

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

  bzoj莫名T。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),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[][L],p[L];
vector<char> s[N];
bool isac(char c){return c>='a'&&c<='z'||c>=''&&c<=''||c=='*';}
bool cmp(const int&a,const int&b)
{
return pre[a]<pre[b];
}
bool check(int n)
{
for (int i=;i<=n;i++) id[i]=i;
sort(id+,id+n+,cmp);
for (int i=;i<=n;i++)
for (int j=;j<pre[id[i-]];j++)
if (s[id[i-]][j]!=s[id[i]][j]) return ;
return ;
}
ul gethash(int k,int l,int r)
{
if (l>r) return ;
return hash[k][r]-hash[k][l-]*p[r-l+];
}
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[]=;for (int i=;i<=L-;i++) p[i]=p[i-]*;
while (T--)
{
n=read();
for (int i=;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[][]=;int len=;bool flag=;
for (int i=;i<=n;i++)
{
int l=s[i].size();
pre[i]=l,suf[i]=-;
for (int j=;j<l;j++)
if (s[i][j]=='*') {pre[i]=j;break;}
for (int j=l-;~j;j--)
if (s[i][j]=='*') {suf[i]=j;break;}
if (pre[i]==l)
if (!len)
{
len=l;
for (int j=;j<l;j++) hash[][j+]=hash[][j]*+s[i][j];
}
else
{
ul tot=;
for (int j=;j<l;j++) tot=tot*+s[i][j];
if (tot!=hash[][len]) {flag=;break;}
}
}
if (!flag) {cout<<"N\n";continue;}
if (!len)
{
if (!check(n)) {cout<<"N\n";continue;}
for (int i=;i<=n;i++)
{
reverse(s[i].begin(),s[i].end());
pre[i]=(int)s[i].size()-suf[i]-;
}
if (!check(n)) {cout<<"N\n";continue;}
cout<<"Y\n";
}
else
{
bool flag=;
for (int i=;i<=n;i++)
if (pre[i]!=s[i].size())
{
hash[][]=;
int l=s[i].size();
for (int j=;j<l;j++) hash[][j+]=hash[][j]*+s[i][j];
if (pre[i]+l--suf[i]>len||gethash(,,pre[i])!=gethash(,,pre[i])||gethash(,len-l+suf[i]+,len)!=gethash(,suf[i]+,l)) {flag=;break;}
int x=pre[i]+;flag=;
for (int j=pre[i];j<=suf[i];j++)
{
if (j==suf[i]) flag=;
if (s[i][j]=='*') continue;
int t=j;
while (s[i][t+]!='*') t++;
while (x+t-j<len-l+suf[i]+&&gethash(,x,x+t-j)!=gethash(,j+,t+)) x++;
if (x+t-j>=len-l+suf[i]+) break;
j=t;
}
if (flag) break;
}
if (flag) cout<<"N\n";else cout<<"Y\n";
}
}
return ;
}

最新文章

  1. js原生ajax请求get post笔记
  2. Linux中ctrl-c, ctrl-z, ctrl-d 区别
  3. 重构第27天 去除上帝类(Remove God Classes)
  4. Web负载均衡的几种方式
  5. AngularJS展示数据的ng-bind指令和{{}} 区别
  6. 常见Android面试题及答案(详细整理)
  7. keyup实现在输入状态不发送搜索请求,停止输入后发送
  8. angular directive自定义指令
  9. Golang 入门 : 数组
  10. 在java项目中使用umeditor
  11. nginx 日志log_format格式
  12. C.字符串(字符)操作
  13. for 练习
  14. VS2010正则批量替换set_和get_
  15. 尚硅谷STRUTS2视频学习笔记
  16. log4net记录系统错误日志到文本文件用法详解
  17. UVa 11404 回文子序列(LCS求最长回文串长度)
  18. python中 try、except、finally 的执行顺序
  19. java---springMVC与strutsMVC的区别
  20. 51nod1469 淋漓字符串(后缀自动机)

热门文章

  1. js页面动态时间展示
  2. (一)SpringBoot2.0基础篇- 介绍及HelloWorld初体验
  3. 如何写一个简单的HTTP服务器(重做版)
  4. Python中print函数中中逗号和加号的区别
  5. nexus实现从windows迁移至Linux平台
  6. Lua学习笔记(7): 模块
  7. 微信 msg_sec_check接口PHP 调用
  8. TCP/IP三次握手四次挥手分析
  9. SICP读书笔记 1.3
  10. 『ACM C++』PTA浙大 | 基础题 - Have Fun with Numbers