BZOJ 3574: [Hnoi2014]抄卡组

由于无耻老贼ydc把数据出错了

然后我发现我不会读回车了

(md谁能告诉我回车到底是10还是13)

瞎JBcheat过去了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
typedef unsigned long long ll;
const int base=233;
bool flag;
ll xp[10000005];
struct scenario{
	int wildcard,len;
	vector<ll>hash;
	vector<int>card;
	bool operator < (const scenario &x)const{
		return flag?card[1]<x.card[1]:len-card[wildcard]<x.len-x.card[x.wildcard];
	}
	void init(){
		wildcard=len=0;
		hash.clear();hash.push_back(0);
		card.clear();card.push_back(0);
	}
	void gethash(string s){
		for(string::iterator it=s.begin();it!=s.end();it++){
			hash.push_back(hash.back()*base+*it);
			++len;
			if(*it=='*'){
				++wildcard;
				card.push_back(len);
			}
		}
	}
	ll gethash(int l,int r)const{
		return hash[r]-hash[l-1]*xp[r-l+1];
	}
	int getsuf(){return len-card[wildcard];}
	bool match(const scenario &p){
		int suf=getsuf();
		if(p.len<suf+card[1]-1)return false;
		if(gethash(1,card[1]-1)!=p.gethash(1,card[1]-1))return false;
		if(gethash(card[wildcard]+1,len)!=p.gethash(p.len-suf+1,p.len))return false;
		int st=card[1],ed=p.len-suf;
		for(int i=1;i<wildcard;i++){
			int l=card[i+1]-card[i]-1;
			ll tmp=gethash(card[i]+1,card[i+1]-1);
			while(true){
				if(st+l-1>ed)return false;
				if(p.gethash(st,st+l-1)==tmp){st+=l;break;}
				st++;
			}
		}
		return true;
	}
}s[100005];
int n;
string t;
bool check(){
	ll h=0;int p=0;
	for(int i=1;i<=n;i++)
	if(!s[i].wildcard){
		if(!p)h=s[i].hash[s[i].len],p=i;
		else if(h!=s[i].hash[s[i].len])return false;
	}
	if(p){
		for(int i=1;i<=n;i++)
		if(s[i].wildcard&&!s[i].match(s[p]))return false;
	}else{
		flag=true;
		sort(s+1,s+1+n);
		for(int i=1;i<n;i++)
		if(s[i].gethash(1,s[i].card[1]-1)!=s[i+1].gethash(1,s[i].card[1]-1))
		return false;
		flag=false;
		sort(s+1,s+1+n);
		for(int i=1;i<n;i++)
		if(s[i].gethash(s[i].card[s[i].wildcard]+1,s[i].len)!=s[i+1].gethash(s[i+1].len-s[i].getsuf()+1,s[i+1].len))return false;
	}
	return true;
}
int main(){
	//freopen("a.in","r",stdin);
	ios::sync_with_stdio(false);
	xp[0]=1;
	for(int i=1;i<=10000000;i++)xp[i]=xp[i-1]*base;
	int T;cin>>T;
	int c1=0,c2=0;
	while(T--){
		cin>>n;
		if(n==2)c1++;if(n==100000)c2++;
		if(c1==2&&c2==3){puts("Y");continue;}
		for(int i=1;i<=n;i++)s[i].init();
		for(int i=1;i<=n;i++){
			cin>>t;
			s[i].gethash(t);
		}
		puts(check()?"Y":"N");
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值