bzoj3574[Hnoi2014]抄卡组
http://www.lydsy.com/JudgeOnline/problem.php?id=3574
我们发现如果所有的字符串都有*,那么只需要比较他们的“前缀”和“后缀”相同即可。“前缀”指第一个*前的字符串,“后缀”指最后一个*后的字符串
如果存在一个字符串没有*,那么要求其他串都能跟这个串匹配,用哈希即可
#include<cstdio> #include<cstdlib> #include<iostream> #include<fstream> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<queue> #include<stack> #include<map> #include<utility> #include<set> #include<bitset> #include<vector> #include<functional> #include<deque> #include<cctype> #include<climits> #include<complex> #include<cassert> //#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef double DB; typedef pair<int,int> PII; typedef pair<DB,DB> PDD; typedef complex<DB> CP; typedef vector<int> VI; #define mmst(a,v) memset(a,v,sizeof(a)) #define mmcy(a,b) memcpy(a,b,sizeof(a)) #define fill(a,l,r,v) fill(a+l,a+r+1,v) #define re(i,a,b) for(i=(a);i<=(b);i++) #define red(i,a,b) for(i=(a);i>=(b);i--) #define fi first #define se second #define mp(a,b) make_pair(a,b) #define pb(a) push_back(a) #define SF scanf #define PF printf #define two(k) (1<<(k)) #define SZ(x) (int(x.size())) #define all(x) (x).begin(),(x).end() #define ire(i,v,x) for(i=0,v=i<SZ(x)?x[i]:0;i<SZ(x);v=x[++i]) template<class T>inline T sqr(T x){return x*x;} template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;} template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} inline int sgn(DB x){if(abs(x)<1e-9)return 0;return(x>0)?1:-1;} const DB Pi=acos(-1.0); int gint() { int res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } LL gll() { LL res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } const int maxn=101000; const int sumlen=20001000; int n; char mem[sumlen];int now; int len[maxn],from[maxn],to[maxn]; int mark[maxn],com,nowlen,maxlen; #define P 991 ULL power[sumlen]; ULL sum[sumlen]; void read() { int i,j; n=gint(); now=0; com=-1; maxlen=0; re(i,1,n) { from[i]=now+1; cin>>mem+now+1; len[i]=strlen(mem+now+1); to[i]=from[i]+len[i]-1; now=to[i]; mark[i]=0; re(j,from[i],to[i])if(mem[j]=='*'){mark[i]=1;break;} if(!mark[i])com=i; upmax(maxlen,len[i]); } power[0]=1; while(nowlen<maxlen)power[nowlen+1]=power[nowlen]*P,nowlen++; re(i,1,now)sum[i]=sum[i-1]*P+mem[i]; } ULL gethash(int l,int r){return sum[r]-sum[l-1]*power[r-l+1];} int ch[maxn]; char RT[sumlen]; int check(int a,int b) { int head=from[b]; for(int l=from[a],r;l<=to[a];l=r+1) { while(mem[l]=='*' && l<=to[a]) l++; if(l>to[a])break; for(r=l;r+1<=to[a] && mem[r+1]!='*';r++); ULL RIG=gethash(l,r); while(head+(r-l+1)-1<=to[b] && gethash(head,head+(r-l+1)-1)!=RIG) head++; if(head+(r-l+1)-1>to[b])return 0; head+=r-l+1; } if(mem[from[a]]!='*') { int i,l=from[a],r; for(r=l;r+1<=to[a] && mem[r+1]!='*';r++); re(i,l,r)if(mem[i]!=mem[from[b]+i-l])return 0; } if(mem[to[a]]!='*') { int i,l,r=to[a]; for(l=r;l-1>=from[a] && mem[l-1]!='*';l--); re(i,l,r)if(mem[i]!=mem[to[b]-(r-i)])return 0; } return 1; } int check() { if(com!=-1) { int i; re(i,1,n) { if(!mark[i] && (len[i]!=len[com] || gethash(from[i],to[i])!=gethash(from[com],to[com])))return 0; if(mark[i] && !check(i,com))return 0; } return 1; } else { int i,j,p=-1; re(i,1,n) { for(ch[i]=0;ch[i]+1<=len[i] && mem[from[i]+ch[i]]!='*';ch[i]++); if(p==-1 || ch[p]<ch[i])p=i; } re(i,1,ch[p])RT[i]=mem[from[p]+i-1]; re(i,1,n)re(j,1,ch[i])if(RT[j]!=mem[from[i]+j-1])return 0; p=-1; re(i,1,n) { for(ch[i]=0;ch[i]+1<=len[i] && mem[to[i]-ch[i]]!='*';ch[i]++); if(p==-1 || ch[p]<ch[i])p=i; } re(i,1,ch[p])RT[i]=mem[to[p]-i+1]; re(i,1,n)re(j,1,ch[i])if(RT[j]!=mem[to[i]-j+1])return 0; } return 1; } int main() { freopen("hs.in","r",stdin); freopen("hs.out","w",stdout); int T=gint(); while(T--) { read(); PF("%c\n",check()?'Y':'N'); } return 0; }