FZU_2275 Game (博弈,kmp模板)

题目链接:FZU_2275 Game

题意

Alice 可以对数字 A 操作,Bob 可以对数字 B 操作,有两种操作:

1、反转,如 1234 反转为 4321;

2、除以 10 向下取整,如 1234/10=123;

Alice 先手,轮流操作,每次操作能选择 1 或 2 操作一次,如果能在有限步内达到 A==B,则 Alice 获胜,否则 Bob 获胜。给出 A,B,问谁能获胜?


思路

因为能反转也能去掉末尾一位,容易想到 Bob 的最优策略是不要改变 B 串的长度,那么当 A 的某个子串为 B 或 B的反转,则 Alice 获胜,否则 Bob 获胜,这就是一个 kmp 判断主串能否找到模式串的匹配的问题。要特判 B 为 0 的时候,Alice 必胜。

整理了 kmp 模板在代码中,时间复杂度 $O(n+m)$ 。


代码实现

#include <cstdio>
#include <cstring>
#include <iostream>
using std::swap;
const int N = 100010;
char s1[N], s2[N]; // s2为模式串,s1为主串
int nex[N];
void get_next(int n2) {
    nex[1] = nex[0] = 0;
    int k = 0;
    for (int i = 2; i < n2; i++) {
        for (; k && s2[k] != s2[i-1]; k = nex[k]);
        if (s2[k] == s2[i-1]) k++;
        nex[i] = k;
    }
}
/* // count版kmp,返回s2在s1中出现的次数(可叠加)
int kmp_count(int n1, int n2) {
    int j = 0, sum = 0;
    for (int i = 0; i < n1; i++) {
        while (s1[i] != s2[j] && j > 0) {
            j = nex[j-1];
        }
        if (s1[i] == s2[j]) j++;
        if (j == n2) {
            sum++;
            j = nex[j-1];
        }
    }
    return sum;
} */
// 返回是否能在s1中找到s2的匹配
bool kmp_match(int n1, int n2) {
    int q = 0, s = 0;
    while (s < n1) {
        for (q = nex[q]; q < n2 && s2[q] == s1[s]; q++, s++);
        if (q == 0) s++;
        else if (q == n2) return true; // return s - n2 + 1; 返回匹配的起始位置
    }
    return false;
}

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%s %s", s1, s2);
        int n1 = strlen(s1), n2 = strlen(s2);
        if (s2[0] == '0' && n2 == 1) puts("Alice");
        else if (n1 < n2) puts("Bob");
        else {
            get_next(n2);
            if (kmp_match(n1, n2)) {
                puts("Alice");
                continue;
            }
            for (int i = 0; i < n2 / 2; i++) swap(s2[i], s2[n2-1-i]);
            get_next(n2);
            if (kmp_match(n1, n2)) {
                puts("Alice");
                continue;
            }
            puts("Bob");
        }
    }
    return 0;
}
View Code

 

posted @ 2019-10-09 21:43  _kangkang  阅读(147)  评论(0编辑  收藏  举报