4212: String Game
Time Limit: 1 Sec
Memory Limit: 128 MB
Submit: 334
Solved: 40
Description
Alice and Bob are playing the following game with strings of letters.
Before the game begins, an initial string and a target string are decided. The initial string is at least as long as the target string. Then, Alice and Bob take turns, starting with the initial string. Bob goes first. In each turn, the current player removes either the first or the last letter of the current string. Once the length of the current string becomes equal to the length of the target string, the game stops. If the string at the end of the game is equal to the target string, Alice wins the game; otherwise Bob wins.
Determine who will win the game if both players are playing optimally.
Input
Each test case starts with N, the number of inputs to process. Each input consists of one line, which contains the initial string, followed by a space, followed by the target string. Each string consists of only lowercase letters. The total input length will be less than 500000 characters.
Output
For each input, output the winner, which will either be Alice or Bob.
Sample Input
5
aba b
bab b
aaab aab
xyz mnk
xyz xyz
Sample Output
Alice
Alice
Bob
Bob
Alice
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;}
template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;}
const int N=5e5+10,M=0,Z=1e9+7,ms=0x3f3f3f3f;
int casenum,casei;
int n,m;
char a[N],b[N];
bool solve()
{
int bef=(n-m)/2;
int beh=n-m-bef;
if(bef==beh)
{
if(strncmp(b+1,a+bef+1,m)==0)return 1;
if(strncmp(b+1,a+bef,m)==0
&&strncmp(b+1,a+bef+2,m)==0)return 1;
}
else
{
if(strncmp(b+1,a+bef+1,m)==0
&&strncmp(b+1,a+bef+2,m)==0)return 1;
}
return 0;
}
int main()
{
scanf("%d",&casenum);
for(casei=1;casei<=casenum;++casei)
{
scanf("%s",a+1);n=strlen(a+1);
scanf("%s",b+1);m=strlen(b+1);
puts(solve()?"Alice":"Bob");
}
return 0;
}
/*
【题意】
给你两个串a和b,5e5>=|a|>=|b|
Alice和Bob依次取数,Bob先手。
每次取数从串a的最开始或最末尾,一直取数,直到|a|==|b|
如果最后剩下的串恰等于b串,那么Alice胜,否则Bob胜。
两人按照最优策略游戏,让你判定最后谁胜。
【类型】
博弈 KMP or strncpy
【分析】
首先,我们肯定可以做一个判定,如果a串中不含有b串,那么显然Bob胜。
判定字符串的包含关系,我们很快就想到KMP算法。
我们发现,Alice的胜利似乎是比Bob要"难"的,因为Bob如果破坏掉所有的模板串,就必胜了。
于是,我们研究Bob。看看Bob最少的操作步数,破坏掉所有的模板串。
如果Bob的可操作步数,不少于这个完全破坏的最小操作步数,那么Bob就必胜啦,这是显然的。
然而,如果Bob的可操作步数,少于这个完全破坏的最小操作步数,Bob就必败么?
会不会Alice遇到必须取字符的时候,Alice的取的字符,会帮助的Bob呢?
这个是很可能的,比如数据{aabaaaaba b},然而这道题的数据水,却可以用这个策略AC。
对于博弈问题,对称式的思维方式常常是十分重要的。
对于取数前原始串和取数后的目标串——
1,如果前后串的长度同奇或同偶,那么说明Alice和Bob的操作数相同。
在这种情况下,Alice可以使得最后剩下的串是恰好中间的串,可以使得最后剩下的串,是恰好中间的串(一定做得到)
或左偏1或右偏1(偏向那边的决定权在于Bob)。
换句话说,就是如果恰好中间的串是模板串,Alice可以必胜。
同时,如果恰好左偏1和右偏1的串都是模板串,Alice一样可以达到必胜。这是Bob所无法改变的必胜态。
2,如果前后串的长度奇偶不同,那么说明Bob比Alice的操作数多一。
在这种情况下,Alice可以使得最后剩下的串,是恰好中间的两个串之一(稍偏左的串或稍偏右的串,偏向哪边的决定权在于Bob)。
换句话说,就是如果恰好中间偏左的串和中间偏右都是模板串,那么Alice一样可以达到必胜态。
我们发现,这要满足存在两个串(或一个串和其自身)与中间位置实现对称,
然而——如果没有这些必胜条件,Alice能否达到其他情况下的必胜态呢?
即,如果有其他的合法目标串位置,Alice是否还一样可以达到呢?
我们进而发现,这是不可能的。
为什么呢?就像是Alice对于Bob,可以通过对称性的策略做限制一样,Bob对Alice也能起到同样的限制作用。
在情况1下,Alice最多只能达到左偏1或右偏1,偏向也是由Bob决定
在情况2下,Alice不会逃脱中间位置。
于是,这道题的就可以被简单地做完啦。甚至KMP都不需要。
【时间复杂度&&优化】
O(n)
*/