• 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
  • 相关阅读:
    85--spring cloud (Ribbon-Eureka注册中心)
    85--spring cloud 入门(springcloud简介)
    84--spring cloud 入门(微服务注册中心介绍)
    83--spring cloud 入门(Eureka注册中心)
    82--JT项目20(订单模块实现/ThreadLocal本地线程变量/Quartz框架)
    81--JT项目19(商品购物车/详情/用户退出)
    80--JT项目18(Dubbo负载均衡/单点登录/注册业务)
    Ajax中post与get的区别
    Process
    Java实现CURL,与把字符串结果写到json文件
  • 原文地址:https://www.cnblogs.com/kangkang-/p/11644577.html
Copyright © 2020-2023  润新知