zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    iOS初级博客的链接
    代理参数问题的思考
    数组里面的选择排序与起泡排序比较
    【C语言】02-函数
    【C语言】01-第一个c程序代码分析
    响应者链的事件分发
    UIController中view的记载流程
    UITabBar的定制
    CommandTabel_代理方法
    来到博客园
  • 原文地址:https://www.cnblogs.com/kangkang-/p/11644577.html
Copyright © 2011-2022 走看看