bzoj 3574: [Hnoi2014]抄卡组 (字符串Hash)
来源:互联网 发布:内涵吧源码 编辑:程序博客网 时间:2024/06/18 10:46
题目描述
传送门
题目大意:’*’可以匹配任意长度个的字符(包含0个),问所有字符串是否两两匹配。
题解
对于两个都包含通配符的字符串,只要Lcp,Lcs的长度都等于到通配符较短的串的长度。
例如aaaa*aaaa和a*aa
只要LCP的长度等于1,LCS的长度等于2即可。剩下的中间部分可以通过通配符进行调整。
按照到第一个通配符的长度排序,然后相邻的用hash判断一下即可。
但是有一种情况 aaaaaaaa和aaa*5*aa,只通过上面的方式判断是不行的。
对于存在完整串的判断,我们需要对于不完整串依次判断他的每一部分是否在完整串中顺序出现。
这个的话直接扫描就可以了。
这道题的读入比较恶心,Re与WA的同学建议先考虑读入的问题。
代码
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define N 10550003#define ULL unsigned long long #define p 2000001001using namespace std;struct data{ int l,r,x,y,len,cnt;}a[1000005];int n,m,T;ULL mi[N],hash[N];char s[N],ch[N];int cmp(data a,data b){ return a.x<b.x;}int cmp1(data a,data b){ return a.y<b.y;}string S;template<typename T>inline void read(T &res){ res=0;T fh=1;char ch=getchar(); while((ch>'9'||ch<'0')&&ch!='-')ch=getchar(); if(ch=='-')fh=-1,ch=getchar(); while(ch>='0'&&ch<='9')res=res*10+ch-'0',ch=getchar(); res*=fh;}inline int gi(){int x;read(x);return x;}int main(){ freopen("input.txt","r",stdin); //freopen("hs.out","w",stdout); T=gi(); mi[0]=1; for (int i=1;i<=10500000;i++) mi[i]=mi[i-1]*p; while (T--) { n=gi(); m=0; int mx=N,opt; for (int i=1;i<=n;i++) { getline(cin,S); int len=S.size(); for (int j=0;j<len;j++) s[j+1]=S[j]; int l=len+1,r=0; for (int j=1;j<=len;j++) { ch[j+m]=s[j]; if (j==1) hash[j+m]=mi[j]*s[j]; else hash[j+m]=hash[j+m-1]+mi[j]*s[j]; if (s[j]=='*') l=min(l,j-1),r=max(r,j+1),a[i].cnt++; } a[i].l=m+1; a[i].r=m+len; a[i].len=len; m+=len; if (l!=len+1) a[i].x=l,a[i].y=len-r+1; else { a[i].x=a[i].y=len; mx=min(mx,len); if (mx==len) opt=i; } } bool pd=true; for (int i=1;i<=n;i++) if (a[i].len-a[i].cnt>mx) { pd=false; break; } if (!pd) { printf("N\n"); continue; } if(mx!=N) { for (int i=1;i<=n;i++) { if (i==opt) continue; int t=a[i].l-1; int l=a[opt].l; for (int j=1;j<=a[i].len;j++) { if (ch[t+j]=='*') continue; while (ch[t+j]!=ch[l]&&l<=a[opt].r) l++; if (ch[t+j]!=ch[l]) { pd=false; break; } l++; } if (!pd) break; } } sort(a+1,a+n+1,cmp); for (int i=1;i<n;i++) { int t=a[i].x; if (!t) continue; if (hash[a[i].l+t-1]!=hash[a[i+1].l+t-1]) pd=false; if (!pd) break; } if (!pd) { printf("N\n"); continue; } sort(a+1,a+n+1,cmp1); for (int i=1;i<n;i++) { int t=a[i].y; if (!t) continue; ULL x,y; if (t!=a[i].len) x=hash[a[i].r]-hash[a[i].r-t]; else x=hash[a[i].r]; if (t!=a[i+1].len) y=hash[a[i+1].r]-hash[a[i+1].r-t]; else y=hash[a[i+1].r]; int l=a[i+1].len-a[i].len; if (l>=0) x*=mi[l]; else y*=mi[-l]; if (x!=y) pd=false; if (!pd) break; } if (pd) printf("Y\n"); else printf("N\n"); }}
阅读全文
0 0
- bzoj 3574: [Hnoi2014]抄卡组 (字符串Hash)
- BZOJ 3574: [Hnoi2014]抄卡组
- BZOJ 3574 HNOI 2014 抄卡组 字符串Hash+STL
- 虚树(bzoj 3572: [Hnoi2014]世界树)
- 【BZOJ 3571】 [Hnoi2014]画框
- BZOJ 3571: [Hnoi2014]画框
- bzoj 3916 friends | 字符串hash
- BZOJ 3916 friend 字符串hash
- bzoj 3572 [Hnoi2014]世界树(虚树+DP)
- bzoj 3572: [Hnoi2014]世界树 (虚树+树形DP+LCA)
- bzoj 4598: [Sdoi2016]模式字符串 (hash+点分治)
- 【BZOJ 3576】 [Hnoi2014]江南乐
- bzoj 3572[HNOI2014]世界树
- [BZOJ 3575] HNOI2014 道路堵塞
- BZOJ 3572: [Hnoi2014]世界树
- BZOJ 3575: [Hnoi2014]道路堵塞
- BZOJ 3576: [Hnoi2014]江南乐
- BZOJ 3576 [Hnoi2014] 江南乐
- BDF2的部门维护页面修改
- C语言的作用
- HashMap HashTable LinkedHashMap TreeMap
- 两道多线程打印题目
- Apache Maven的插件概述
- bzoj 3574: [Hnoi2014]抄卡组 (字符串Hash)
- Map用法
- ECLIPSE 快捷键
- 组合模式Composite(结构型)
- 15、jQuery插件之slider幻灯片插件(可悬停控制)
- js实现跨域
- MarkdownView:Markdown 文档预览视图组件
- Android NDK入门
- 移动端图片上传的实践