2017年集训队第四场选拔赛 -string Game

 
Problem A: String Game

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 55   Solved: 20
[ Submit][ Status][ Web Board]

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 bbab
baaab aab
xyz mnk
xyz xyz

Sample Output

Alice
Alice
Bob
Bob
Alice


首先看到此题,我们应该先定一个目标,即求出Alice胜的情形。根据题意应该想到的是,子串应该在父串中间时,Alice会赢,我们先考虑简单情形,设父串长度为n,子串长度为m,(假设n >= m),且n和m同奇偶,那么子串的起始位置应该是,mid = (n - m)/ 2;
为什么要这么想呢,首先,Bob和Alice只能一次取一个字符,达到len2时,判断现在的父串与子串是否相同,那么假设我们把子串放在中间,子串两边的字符数相等时,则必定Alice胜,为了直观,我们假设父串为a1 a2 a3 a4... an,子串为b1 b2 b3 ...bm 那么,这种情形便是:
a1 a2 a3 ... b1 b2 .. bm ... an,我们只需b1前面的字符数与bm后面的字符数相等即可(且同奇偶时数目为mid - 1)
接下来我们考虑一奇一偶的情形,若要Alice胜,这时候我们把子串放在父串中间是行不通的,因为b1前面的字符数为mid - 1,而bm后面的字符数却是mid,这时候只要Bob一直取前面的字符,Alice必输,这里我们就发现了一个规律,前后字符数若不相同则必定Alice输,那么我们为了让Alice赢则必定是要将前后的字符变成一样的,这时候因为一个子串已经不够用了,我们可以再加一个子串,这个位置容易想到的是把新的b1放在mid+1的位置,这时候就导致前后的字符数均等于mid - 1了,为什么会导致前后字符数相当于mid - 1呢,这是因为Bob只能在前后取字符,他如果要赢,则必定要消除这两个子串,显然,要消除第一个子串他必须选择取完前面的mid + 1个字符,或者从后面取完mid + 1个字符,但这是行不通的,因为当他取第mid个字符时,两个串的长度相等了,并且必定留下了子串。
那么由于在一奇一偶中,取两个串是可以的,是否在同奇偶的情形下也可以呢,按照之前的想法,我们可以放两个串,来使得第一个串的b1前面的字符数等于第二个串bm后面的字符数,并且,为了保证其连续可行性,我们先尝试把两个b1放在mid - 1和mid + 1位置,那么此时,Bob要获胜必定要取完前mid + 1个字符,与之前的思路类似,此情形下,Alice必胜。
放置两个串的情形是否有其他的呢,简单证明其不存在,我们尝试把两个b1放在mid - 2 和mid + 2,此时为了消除第一个串,Bob只需取完mid - 2个字符,若要为了消除第二个串,则只需取完后面的mid - 2个字符,而此时,Alice必定要取走mid  - 3个字符,为了不让Bob得胜,他必定要取后面的字符,而此时,Bob在取第mid - 1个字符时,就可以选择取后面的字符,Alice 必输。
下面给出代码,有点乱...
#include <iostream>
#include <cstdio>
#include <string>
#include <cmath>
#include <vector>
#include <set>
#include <cstring>
#include <algorithm>
using namespace std;
int main() {
     int n;
     string str1, str2;
     cin >> n;
     while (n--) {
         cin >> str1 >> str2;
         int len1 = str1.length();
         int len2 = str2.length();
         if (len1 < len2) cout << "Bob" << endl;
         else {
             int t = (len1 - len2) / 2;
             if (len1 % 2 == len2 % 2) {
                 int flag = 1;
                 for ( int i = 0; i < len2; i++) {
                     if (str1[t + i] != str2[i]) {
                         flag = 0;
                         break ;
                     }
                 }
                 if (flag) {
                     cout << "Alice" << endl;
                 }
                 else if (len1 == len2) {
                     cout << "Bob" << endl;
                 }
                 else {
                     flag = 1;
                     for ( int i = 0; i < len2; i++) {
                         if (str1[t + i + 1] != str2[i]) {
                             flag = 0;
                             break ;
                         }
                     }
                     for ( int i = 0; i < len2; i++) {
                         if (str1[t + i - 1] != str2[i]) {
                             flag = 0;
                             break ;
                         }
                     }
                     if (flag) cout << "Alice" << endl;
                     else cout << "Bob" << endl;
                 }
             }
             else {
                 int flag = 1;
                 for ( int i = 0; i < len2; i++) {
                     if (str2[i] != str1[t + i]) {
                         flag = 0;
                         break ;
                     }
                 }
                 for ( int i = 0; i < len2; i++) {
                     if (str2[i] != str1[t + i + 1]) {
                         flag = 0;
                         break ;
                     }
                 }
                 if (flag) cout << "Alice" << endl;
                 else cout << "Bob" << endl;
             }
         }
     }
     return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值