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;
  }
View Code

 

posted @ 2016-03-08 19:44  maijing  阅读(520)  评论(0编辑  收藏  举报