链接:https://www.nowcoder.com/acm/contest/109/F
来源:牛客网
给定两个串S和T,|S| >= |T|。
alice和bob轮流操作串S,bob先手。
对于每次操作,alice或bob会选择删掉S的第一位或最后一位。
当操作以后的串的长度等于|T|时,游戏停止。
如果停止时的串=T,则alice获胜,否则bob获胜。
问在alice和bob均采取最优策略的情况下,谁赢?
t组数据
1<=|T|<=|S|<=500000,t<=1000
字符串总长度不超过1000000
考虑简化表示状态
设左边已经删掉了L个数,右边已经删掉了R个数
那么用R-L来表示当前状态,可以用KMP求出有哪些目标状态
一开始R-L为0,每一次操作可以让它+1或者-1,双方轮流操作,总共|S|-|T|次操作,双方都用最优策略看最后是否能到达目标状态
显然所有的目标状态奇偶性相同
当|S|-|T|为奇数时,最后一次操作是Bob做,它肯定往不是目标状态走,那么一个位置在最后一次操作前是目标状态当且仅当它+1它-1都是目标状态
现在就全部转化成|S|-|T|为偶数的情况
假如0是目标状态,那么显然Alice会赢,无论Bob往哪里走Alice后手都可以把他拉回来
如果0不是,并且-2和2不全是,那么Bob一定会朝不是的那一边走,Alice无论如何都没有办法将它拉回到是的那一边了
因此Alice会赢当且仅当0是目标状态或者-2和2都是目标状态
否则都是Bob赢
#include
#include
#include
#include
#include
#include
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define N 500005
using namespace std;
int n,m,t,cnt[N],nx[N],ct[N];
char st[N],ch[N];
void kmp()
{
n=strlen(st+1),m=strlen(ch+1);
int j=0;
fo(i,2,m)
{
while(j&&ch[i]!=ch[j+1]) j=nx[j];
if(ch[i]==ch[j+1]) j++;
nx[i]=j;
}
j=0;
fo(i,1,n)
{
while(j&&st[i]!=ch[j+1]) j=nx[j];
if(st[i]==ch[j+1]) j++;
if(j==m)
{
if((n-m)%2==0) cnt[++cnt[0]]=n-i-(i-m);
else ct[++ct[0]]=n-i-(i-m);
j=nx[j];
}
}
}
int main()
{
cin>>t;
while(t--)
{
scanf("\n%s",st+1);
scanf("%s",ch+1);
cnt[0]=0,ct[0]=0;
kmp();
if((n-m)%2!=0)
{
sort(ct+1,ct+ct[0]+1);
fo(i,2,ct[0]) if(ct[i]-ct[i-1]==2) cnt[++cnt[0]]=ct[i]-1;
}
bool pd=0,pd1=0,pd2=0;
fo(i,1,cnt[0])
{
if(cnt[i]==0) pd=1;
if(cnt[i]==2) pd1=1;
if(cnt[i]==-2) pd2=1;
}
if(pd||(pd1&&pd2)) printf("Alice\n");
else printf("Bob\n");
}
}