太久没写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"); } }