1. 程式人生 > >Newcoder 109 F.玩遊戲(博弈論)

Newcoder 109 F.玩遊戲(博弈論)

Description

給定兩個串SSTTST|S|\ge |T|

alicealicebobbob輪流操作串SSbobbob先手。

對於每次操作,alicealicebobbob會選擇刪掉SS的第一位或最後一位。

當操作以後的串的長度等於T|T|時,遊戲停止。

如果停止時的串=T=T,則alicealice獲勝,否則bobbob獲勝。

問在alicealicebobbob均採取最優策略的情況下,誰贏?

Input

第一行一個整數TT表示資料組數。

接下來TT行每行兩個整數字符串S

,TS, T

(T1000,1TS5105,(S+T)106)(T\le 1000,1\le |T|\le |S|\le 5\cdot 10^5,\sum(|S|+|T|)\le 10^6)

Output

TT行。對於每組資料,alicealice贏輸出Alice'Alice',$ bob贏輸出’Bob’$。

Sample Input

5 aba b bab b aaab aab xyz mnk xyz xyz

Sample Output

Alice Alice Bob Bob Alice

Solution

一.若S=T|S|=|T|,此時S=TS=T則後手勝,否則先手勝

二.若S>T|S|>|T|,記n=S,m=T,t=nmn=|S|,m=|T|,t=n-m,那麼先手可以操作x=t2x=\lceil\frac{t}{2}\rceil次,後手可以操作y=t2y=\lfloor\frac{t}{2}\rfloor次,記[li,ri][l_i,r_i]

SS中所有可以與TT匹配的區間,那麼有li1+nri=tl_i-1+n-r_i=t

1.若tt為偶數,那麼x=yx=y,我們首先證明先手必然可以破壞所有滿足li1̸[x1,x+1]l_i-1\not\in[x-1,x+1]的匹配,先手首先任選一邊刪去一個,之後後手刪哪邊先手就刪另一邊,這樣可以保證兩邊都至少刪去了x1x-1次,那麼所有這種匹配都會因為li1<x1l_i-1<x-1nri<x1n-r_i<x-1被破壞

注意到先手可以破壞一邊至多xx次,故對於li1=xl_i-1=x的匹配顯然可以儲存下來,但是對於li1=x±1l_i-1=x\pm 1的情況,如果只存在一個匹配滿足該條件,那麼先手只需儘可能刪除一邊即可破壞該匹配,故此時必須至少存在兩個匹配使得li1=x1,lj1=x+1l_i-1=x-1,l_j-1=x+1,如此先手無論怎麼刪都至少會有一個匹配儲存下來

2.若tt為奇數,那麼x=y+1x=y+1,同理至少需要兩個匹配使得li1=x,lj1=x+1l_i-1=x,l_j-1=x+1,這樣先手無論刪哪一邊,只要後手刪另一邊,就可以保證至少有一個匹配儲存下來

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=500005;
int T,n,m;
char s[maxn],t[maxn];
bool check(int x)
{
	for(int i=x+1,j=1;j<=m;i++,j++)
		if(s[i]!=t[j])return 0;
	return 1;
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%s%s",s+1,t+1);
		n=strlen(s+1),m=strlen(t+1); 
		int flag=0;
		if(n==m)
		{
			if(strcmp(s+1,t+1)==0)flag=1;
		}
		else
		{
			if((n-m)&1)
			{
				if(check((n-m)/2)&&check((n-m)/2+1))flag=1;
			}
			else 
			{
				if(check((n-m)/2)||check((n-m)/2-1)&&check((n-m)/2+1))flag=1;
			}
		}
		if(flag)printf("Alice\n");
		else printf("Bob\n");
	}
	return 0;
}