[LOJ6377]AStringGame

太久没写SAM感觉自己已经是个废人了23333

先建母串的SAM,然后这个游戏其实就是在SAM的节点上乱走,不能走的人输,这是一个经典的nim游戏,直接算SG值即可

这大概算是新男人八题里比较清真的一道?

#include<stdio.h>
#include<string.h>
int max(int a,int b){return a>b?a:b;}
struct sam{
	int fa,v,ch[26];
}t[200010];
int M,las;
void extend(int c){
	int p=las,np=++M,q,nq;
	t[np].v=t[p].v+1;
	while(p&&t[p].ch[c]==0){
		t[p].ch[c]=np;
		p=t[p].fa;
	}
	if(!p)
		t[np].fa=1;
	else{
		q=t[p].ch[c];
		if(t[q].v==t[p].v+1)
			t[np].fa=q;
		else{
			nq=++M;
			t[nq]=t[q];
			t[nq].v=t[p].v+1;
			t[np].fa=t[q].fa=nq;
			while(p&&t[p].ch[c]==q){
				t[p].ch[c]=nq;
				p=t[p].fa;
			}
		}
	}
	las=np;
}
char s[100010];
int pos[110],sg[200010],c[100010],p[200010];
void sort(){
	int i,m;
	memset(c,0,sizeof(c));
	m=0;
	for(i=1;i<=M;i++){
		c[t[i].v]++;
		m=max(m,t[i].v);
	}
	for(i=1;i<=m;i++)c[i]+=c[i-1];
	for(i=M;i>0;i--)p[c[t[i].v]--]=i;
}
int main(){
	int n,i,j,x,cnt[27];
	while(~scanf("%s",s)){
		memset(t,0,sizeof(t));
		M=las=1;
		for(i=0;s[i];i++)extend(s[i]-'a');
		scanf("%d",&n);
		for(i=1;i<=n;i++){
			scanf("%s",s);
			for(j=0,x=1;s[j];j++)x=t[x].ch[s[j]-'a'];
			pos[i]=x;
		}
		sort();
		for(i=M;i>0;i--){
			memset(cnt,0,sizeof(cnt));
			for(j=0;j<26;j++){
				if(t[p[i]].ch[j]&&sg[t[p[i]].ch[j]]<27)cnt[sg[t[p[i]].ch[j]]]++;
			}
			for(j=0;cnt[j];j++);
			sg[p[i]]=j;
		}
		for(i=1,x=0;i<=n;i++)x^=sg[pos[i]];
		puts(x?"Alice":"Bob");
	}
}

猜你喜欢

转载自www.cnblogs.com/jefflyy/p/9096061.html