「雅礼集训 2017 Day4」编码

传送门

嗯,根据(nekko)大佬的说法跑去搞(SAM)建后缀树,然后发现(Trie)就过了

每个串最多有一个模糊字符,且只能是(0/1),那么考虑(2-sat)

我们发现如果把所有字符串建成一颗(Trie),那么就可以前缀优化建图,因为每个点的祖先都是自己的一个前缀

当然后缀树也可以做到,不过没必要

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define mid ((l+r)>>1)
#define y1 qwq 
	inline int read()
	{
		int x=0;char ch,f=1;
		for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
		if(ch=='-') f=0,ch=getchar();
		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
		return f?x:-x;
	}
	const int N=3e6+10,inf=1<<30;
	int n,m,siz;
	char s[N];
	int p[N],pre[N],f[N];
	int head[N],cnt;
	struct point
	{
		int nxt,to;
		point(){}
		point(const int &nxt,const int &to):nxt(nxt),to(to){}
	}a[N<<2];
	inline void link(int x,int y)
	{
		a[++cnt]=(point){head[x],y};head[x]=cnt;
	}
	struct Tire
	{
		vector<int> v[N];
		int rt=1,sum=0,tot=1,son[N][2];
		inline void insert(int n,int id)
		{
			int x=rt;
			for(int i=1;i<=n;++i)
			{
				int k=s[i]-'0';
				if(!son[x][k]) son[x][k]=++tot;
				x=son[x][k];
			}
			v[x].push_back(id);
		}
		inline void dfs(int x)
		{
			int len=v[x].size();
			for(int i=0;i<len;++i)
			{
				p[++sum]=v[x][i];
				pre[p[sum]]=++siz;
				f[pre[p[sum]]]=++siz;
				f[siz]=pre[p[sum]];
				//p 选了 fp没选
				//pre 选了 fpre没选 
				link(p[sum],pre[p[sum]]);
				//这个选了,这个及之前选了 
				link(f[pre[p[sum]]],f[p[sum]]);
				//这个及之前不选,这个不选 
				if(sum!=1)
				{
					link(pre[p[sum-1]],pre[p[sum]]);
					//上一个之前选了,这个及之前选了 
					link(f[pre[p[sum]]],f[pre[p[sum-1]]]);
					//这个及之前不选,上一个之前不选 
					link(pre[p[sum-1]],f[p[sum]]);
					//上一个及之前选了,这个不选 
					link(p[sum],f[pre[p[sum-1]]]);
					//选这个,上一个及之前不选 
				}
			}
			if(son[x][0]) dfs(son[x][0]);
			if(son[x][1]) dfs(son[x][1]);
			sum-=len;
		}
	}T;
	int dfn[N],low[N],st[N],col[N];
	int idx,top,num;
	inline void tarjan(int now)
	{
		dfn[now]=low[now]=++idx;
		st[++top]=now;
		for(int i=head[now];i;i=a[i].nxt)
		{
			int t=a[i].to;
			if(!dfn[t])
			{
				tarjan(t);
				low[now]=min(low[now],low[t]);
			}
			else if(!col[t]) low[now]=min(low[now],dfn[t]);
		}
		if(dfn[now]==low[now])
		{
			col[now]=++num;
			while(st[top]!=now) col[st[top--]]=num;
			--top;
		}
	}
	inline void main()
	{
		n=read();siz=n;
		for(int i=1;i<=n;++i)
		{
			scanf("%s",s+1);
			int k=0,len=strlen(s+1);
			for(int j=1;j<=len;++j) if(s[j]=='?') k=j;
			f[i]=++siz;f[siz]=i;
			if(k)
			{
				s[k]='0';T.insert(len,f[i]);
				s[k]='1';T.insert(len,i);
			}
			else link(f[i],i),T.insert(len,i);
		}
		T.dfs(T.rt);
		for(int i=1;i<=siz;++i)
			if(!dfn[i]) tarjan(i);
		for(int i=1;i<=siz;++i)
			if(col[i]==col[f[i]]) return(void)puts("NO");
		puts("YES");
	}
}
signed main()
{
	//freopen("haha.in","r",stdin);
	red::main();
	return 0;
}
原文地址:https://www.cnblogs.com/knife-rose/p/12708949.html