본문 바로가기

알고리즘/백준 문제 풀이

[C++] 25456번 궁금한 시프트

728x90

https://www.acmicpc.net/problem/25456


 

26/02/11

 

 

1067번 이동 문제와 매우 유사하다.


 

문제 접근 방식:

 

 

문제에서 주어진 코드를 잘 보면, 두 문자열 $S, T$를 각각 $s, t$만큼 offset을 두고, $S[(s+i)\text{mod }N] = T[(t+i)\text{mod }N] = 1$인 경우 cnt값에 1을 더해주는 코드이다.

문제의 요구사항은 cnt의 최댓값을 찾는 것인데, 결국 이것도 1067번 이동 문제와 똑같은 흐름으로 흘러간다.

크기가 $N$으로 같은 두 배열이 주어졌을 때의 최댓값을 구하는 것인데, 여기선 문자열로 주어진 것만 다르다.

이동문제와 마찬가지로, 배열 $S$를 2배 길이로 만들어주고, 배열 $T$를 뒤집어서 FFT한번 수행하면 충분하다.

계수 또한 최대 $500\ 000$이기 때문에 $998\ 244\ 353$으로 NTT를 돌려도 충분하다.


아래는 내가 위의 접근 방식과 같이 작성한 C++ 코드이다. 더보기를 누르면 확인할 수 있다.

더보기
// 25456번 궁금한 시프트
// NTT
#include <iostream>
#include <vector>

using namespace std;
#define fastio ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define endl '\n'
typedef long long ll;

template<int MOD, int G>
struct NTT{
private:
    inline int mul_mod(int a, int b) const {return (ll)a*b%MOD;}
    inline int pow_mod(int a, int e) const {
        int res = 1;
        while (e > 0){
            if (e & 1) res = mul_mod(res, a);
            a = mul_mod(a, a);
            e >>= 1;
        }
        return res;
    }
    inline int mod_inv(int a) const {return pow_mod(a, MOD-2);}
public:
    void iter_NTT(vector<int>& a, int invert){
        int n = (int)a.size();
        for (int i = 1, j = 0; i < n; ++i){
            int bit = n >> 1;
            while (j & bit){
                j ^= bit;
                bit >>= 1;
            }
            j ^= bit;
            if (i < j) swap(a[i], a[j]);
        }
        for (int len = 2; len <= n; len <<= 1){
            int wlen = pow_mod(G, (MOD-1)/len);
            if (invert) wlen = mod_inv(wlen);
            for (int i = 0; i < n; i += len){
                int w = 1;
                for (int j = 0; j < len / 2; ++j){
                    int u = a[i+j];
                    int v = mul_mod(w, a[i+j+len/2]);
                    int x = u+v; if (x >= MOD) x -= MOD;
                    int y = u-v; if (y < 0) y += MOD;
                    a[i+j] = x;
                    a[i+j+len/2] = y;
                    w = mul_mod(w, wlen);
                }
            }
        }
        if (invert){
            int inv = mod_inv(n);
            for (int i = 0; i < n; ++i){
                a[i] = mul_mod(a[i], inv);
            }
        }
    }
    vector<int> convolution(vector<int> a, vector<int> b){
        int Sa = (int)a.size(), Sb = (int)b.size();
        int n = 1;
        while (n < Sa+Sb-1){n <<= 1;}
        a.resize(n); b.resize(n);
        iter_NTT(a, 0); iter_NTT(b, 0);
        for (int i = 0; i < n; ++i){
            a[i] = mul_mod(a[i], b[i]);
        }
        iter_NTT(a, 1);
        a.resize(Sa+Sb-1);
        return a;
    }
};

int main(void){
    fastio

    string S, T;
    getline(cin, S);
    getline(cin, T);
    int N = (int)S.size();
    vector<int> A(2*N, 0), B(N, 0);
    for (int i = 0; i < N; ++i){
        if (S[i] == '1') {
            A[i] = 1;
            A[i+N] = 1;
        }
    }
    for (int i = 0; i < N; ++i){
        if (T[i] == '1'){
            B[N-i-1] = 1;
        }
    }
    NTT<998'244'353, 3> ntt;
    auto C = ntt.convolution(A, B);
    int ans = 0;
    for (int i = N; i < 2*N; ++i){
        ans = max(ans, C[i]);
    }
    cout << ans;
    return 0;
}
728x90

'알고리즘 > 백준 문제 풀이' 카테고리의 다른 글

[C++] 20176번 Needle  (0) 2026.02.16
[C++] 10531번 Golf Bot  (0) 2026.02.15
[C++] 1067번 이동  (0) 2026.02.13
[Python] 1165번 단어퍼즐  (0) 2026.02.07
[C++] 11670번 초등 수학 / 30887번 Basic Math  (0) 2026.02.06