卧薪尝胆,厚积薄发。
是男人就过8题——Pony.ai AStringGame
Date: Fri Aug 17 16:08:19 CST 2018 In Category: NoCategory

Description:

有一个模板串和 $n$ 个模板串的子串,轮流从 $n$ 个字符串中选一个并在后面添加一个字符,要求新的字符串还是模板串的子串,不能操作者输,问先后手谁能赢。
$1\le |T| \le 100000$ $1\le n \le 100$

Solution:

添加字符相当于 $SAM$ 上状态的转移,对模板串建出后缀自动机,在后缀自动机的 $DAG$ 上沿转移边递推 $SG$ 函数,最后把 $n$ 个字符串对应状态的 $SG$ 异或起来判一下就好了。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define MAXL 100010
char str[MAXL];
struct node
{
int tr[26],par,maxl;
}s[MAXL << 1];
int last = 1,root = 1,ptr = 1;
int newnode(int k){++ptr;s[ptr].maxl = k;return ptr;}
void extend(int k)
{
int p = last;
int np = newnode(s[p].maxl + 1);
for(;p && s[p].tr[k] == 0;p = s[p].par)s[p].tr[k] = np;
if(p == 0)s[np].par = root;
else
{
int q = s[p].tr[k];
if(s[p].maxl + 1 == s[q].maxl)s[np].par = q;
else
{
int nq = newnode(s[p].maxl + 1);
memcpy(s[nq].tr,s[q].tr,sizeof(s[q].tr));
s[nq].par = s[q].par;
s[q].par = s[np].par = nq;
for(;p && s[p].tr[k] == q;p = s[p].par)s[p].tr[k] = nq;
}
}
last = np;
return;
}
int n;
#define MAXN 100
int getpos(char c[])
{
int p = root;
int l = strlen(c + 1);
for(int i = 1;i <= l;++i)
{
p = s[p].tr[c[i] - 'a'];
}
return p;
}
int c[MAXL << 1],a[MAXL << 1];
int SG[MAXL << 1];
int vis[MAXL << 1];
void getSG()
{
memset(c,0,sizeof(c));
memset(a,0,sizeof(a));
int l = strlen(str + 1);
for(int i = 1;i <= ptr;++i)c[s[i].maxl]++;
for(int i = 1;i <= l;++i)c[i] += c[i - 1];
for(int i = ptr;i >= 1;--i)a[c[s[i].maxl]--] = i;
memset(SG,0,sizeof(SG));
memset(vis,0,sizeof(vis));
for(int i = ptr;i >= 1;--i)
{
int u = a[i];
for(int k = 0;k < 26;++k)if(s[u].tr[k] != 0)vis[SG[s[u].tr[k]]] = u;
int k;
for(k = 0;(k <= 26 && vis[k] == u);++k);
SG[u] = k;
}
return;
}
int main()
{
while(scanf("%s",str + 1) != EOF)
{
memset(s,0,sizeof(s));
last = root = ptr = 1;
int l = strlen(str + 1);
for(int i = 1;i <= l;++i)extend(str[i] - 'a');
getSG();
scanf("%d",&n);
int nim = 0;
for(int i = 1;i <= n;++i)
{
scanf("%s",str + 1);
nim ^= SG[getpos(str)];
}
if(nim == 0)puts("Bob");
else puts("Alice");
}
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡