Codeforces Round 951 (Div. 2) D. Fixing a Binary String 题解

Codeforces Round 951 (Div. 2) D. Fixing a Binary String 题解

题意

You are given a binary string s s s of length n n n, consisting of zeros and ones. You can perform the following operation exactly once:

  1. Choose an integer p p p ( 1 ≤ p ≤ n 1 \le p \le n 1pn).
  2. Reverse the substring s 1 s 2 … s p s_1 s_2 \ldots s_p s1s2sp. After this step, the string s 1 s 2 … s n s_1 s_2 \ldots s_n s1s2sn will become s p s p − 1 … s 1 s p + 1 s p + 2 … s n s_p s_{p-1} \ldots s_1 s_{p+1} s_{p+2} \ldots s_n spsp1s1sp+1sp+2sn.
  3. Then, perform a cyclic shift of the string s s s to the left p p p times. After this step, the initial string s 1 s 2 … s n s_1s_2 \ldots s_n s1s2sn will become s p + 1 s p + 2 … s n s p s p − 1 … s 1 s_{p+1}s_{p+2} \ldots s_n s_p s_{p-1} \ldots s_1 sp+1sp+2snspsp1s1.

For example, if you apply the operation to the string 110001100110 with p = 3 p=3 p=3, after the second step, the string will become 011001100110, and after the third step, it will become 001100110011.

A string s s s is called k k k-proper if two conditions are met:

  • s 1 = s 2 = … = s k s_1=s_2=\ldots=s_k s1=s2==sk;
  • s i + k ≠ s i s_{i+k} \neq s_i si+k=si for any i i i ( 1 ≤ i ≤ n − k 1 \le i \le n - k 1ink).

For example, with k = 3 k=3 k=3, the strings 000, 111000111, and 111000 are k k k-proper, while the strings 000000, 001100, and 1110000 are not.

You are given an integer k k k, which is a divisor of n n n. Find an integer p p p ( 1 ≤ p ≤ n 1 \le p \le n 1pn) such that after performing the operation, the string s s s becomes k k k-proper, or determine that it is impossible. Note that if the string is initially k k k-proper, you still need to apply exactly one operation to it.

Input
Each test consists of multiple test cases. The first line contains one integer t t t ( 1 ≤ t ≤ 1 0 4 1 \le t \le 10^4 1t104) — the number of test cases. The description of the test cases follows.
The first line of each test case contains two integers n n n and k k k ( 1 ≤ k ≤ n 1 \le k \le n 1kn, 2 ≤ n ≤ 1 0 5 2 \le n \le 10^5 2n105) — the length of the string s s s and the value of k k k. It is guaranteed that k k k is a divisor of n n n.
The second line of each test case contains a binary string s s s of length n n n, consisting of the characters 0 and 1.
It is guaranteed that the sum of n n n over all test cases does not exceed 2 ⋅ 1 0 5 2 \cdot 10^5 2105.

Output
For each test case, output a single integer — the value of p p p to make the string k k k-proper, or − 1 -1 1 if it is impossible.
If there are multiple solutions, output any of them.

题目解析

  • 我们先不管操作考虑一下什么形式的串是满足条件的。
    • s [ i ] s[i] s[i] != s [ i + k ] s[i+k] s[i+k]
    • s [ i ] = s [ i + 1 ] = . . . = s [ i + k − 1 ] s[i] = s[i+1] =...=s[i+k-1] s[i]=s[i+1]=...=s[i+k1]
  • 要同时满足上述要求,答案的形式只有两种,要么从 1 1 1 开始,要么从 0 0 0 开始。
  • 我们再思考一下操作一次后,串本质上的变化是什么。
  • 我们发现本质上就是把串 s s s 分为两段 A A A B B B,在用 B B B A 的逆序 A的逆序 A的逆序 拼起来。
  • 答案只有两个,我们用 B + A 逆 B+A逆 B+A 是否等于 a n s ans ans,你能想到什么?
  • 字符串 h a s h hash hash

AC代码

注:我用的是 B a s e = 131 , m o d = 805306457 Base=131,mod=805306457 Base=131,mod=805306457 的单模hash,如果想要更保险,可以考虑使用多模hash。

import sys

input = lambda: sys.stdin.readline().rstrip("\r\n")
out = sys.stdout.write
def S():
    return input()
def I():
    return int(input())
def MI():
    return map(int, input().split())
def MF():
    return map(float, input().split())
def MS():
    return input().split()
def LS():
    return list(input().split())
def LI():
    return list(map(int, input().split()))
def print1(x):
    return out(str(x) + "\n")
def print2(x, y):
    return out(str(x) + " " + str(y) + "\n")
def print3(x, y, z):
    return out(str(x) + " " + str(y) + " " + str(z) + "\n")
def Query(i, j):
    print3('?', i, j)
    sys.stdout.flush()
    qi = I()
    return qi
def print_arr(arr):
    out(' '.join(map(str, arr)))
    out(str("\n"))
# ----------------------------- # ----------------------------- #
base = 131
base1 = 13331
mod = 805306457
mod1 = 1610612741

def solve():
    def get_hs(h, l, r):
        return (h[r] - (h[l - 1] * pbase[r-l+1] % mod) + mod) % mod

    n, k = MI()
    s = S()
    pre = [0]*(n+1)
    pbase = [1]*(n+1)
    for i in range(1,n+1):
        pre[i] = (pre[i-1] * base + ord(s[i-1]) - ord('0')) % mod
        pbase[i] = pbase[i-1] * base % mod
    past = [0]*(n+1)
    for i in range(1,n+1):
        past[i] = (past[i-1] * base + ord(s[n - i]) - ord('0')) % mod

    ans1,ans2 = 0,0
    for i in range(n):
        ans1 = (ans1*base + ((i//k) & 1)) % mod
        ans2 = (ans2*base + ((i//k) & 1 ^ 1)) % mod

    for p in range(1,n+1):
        now = (get_hs(pre, p+1,n)*pbase[p] + get_hs(past, n + 1 - p, n)) % mod
        if now == ans1 or now == ans2:
            print1(p)
            return

    print1(-1)


for _ in range(I()):
    solve()
  • 22
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

farawaytravelerchy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值