https://www.acmicpc.net/problem/14437
주어진 문자열은 사실상 장식이고 꽤 어려운 동적 계획법 문제이다. 이 포스트에서는 1차원 테이블과 슬라이딩 윈도우를 결합한 방법을 소개한다.
다음 테이블 2개를 정의한다.
dp_old(i) := 이전 인덱스 문자까지 총 i만큼의 숫자를 소진해서 문자열을 바꾸는 경우의 수
dp(i) := 현재 인덱스 문자까지 총 i만큼의 숫자를 소진해서 문자열을 바꾸는 경우의 수
이미 바꾼 문자는 다시는 바꿀 수 없으므로 이전 1~25만큼 바꿨을 때 문자열이 변하는 경우를 테이블에 반영하면서 전진하면 된다. 이때 처음 dp_old(0)은 공집합 1로 규정한다.
그리고 우리는 dp를 계산해야 되는데 문제의 k가 최대 25라는 조건이 있으므로 $dp(i) = \sum\limits_{x = i - 25}^{25} dp_{old}(x)$ 이와 같은 식을 계산하도록 한다.
여기서 추가 최적화가 필요한데 바로 문자를 1~25만큼 바꾸는 경우를 매 계산마다 일일이 더하지 않고 누적 합으로 관리하도록 한다. 누적합을 하지 않고도 정답을 받을 수 있다고 하니 참고하도록 한다.
누적합을 사용하면 인덱스 25까지는 그냥 더하면 되고 26부터 범위를 벗어난 값을 빼가면서 25 만큼의 곱셈 상수를 줄일 수 있다.
모든 i에 대해 계산을 하면 계산된 dp를 dp_old로 넘겨 다음 인덱스에 대한 테이블을 계산할 준비를 하도록 한다.
위 과정대로 동적 계획법을 수행하면 시간 복잡도 $O(s|N|)$ (N은 입력으로 주어진 문자열)으로 문제를 해결할 수 있다.
전체 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,avx,avx2,fma")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include "bits/stdc++.h"
#include "ext/rope"
using namespace std;
using namespace __gnu_cxx;
using ll = long long;
using pii = pair<int, int>;
const int mod = 1e9 + 7;
int x;
string s;
int len;
vector<ll> window;
vector<ll> dp;
void solve()
{
cin >> x >> s;
window.resize(x + 1);
dp.resize(x + 1);
window[0] = 1;
len = s.size();
for (int i = 0; i < len; i++)
{
ll pref = 0;
for (int j = 0; j <= min(25, x); j++)
{
pref += window[j];
pref %= mod;
dp[j] = pref;
}
for (int j = 26; j <= x; j++)
{
pref += window[j];
pref -= window[j - 26];
while (pref < 0) pref += mod;
pref %= mod;
dp[j] = pref;
}
window = dp;
}
cout << dp[x];
}
int main()
{
#ifdef LOCAL
freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
cin.tie(nullptr);
ios::sync_with_stdio(false);
solve();
}
|
cs |
제출 기록
'백준 > DP' 카테고리의 다른 글
백준 14517 - 팰린드롬 개수 구하기 (Large) (0) | 2022.07.20 |
---|---|
[ICPC] 백준 23342 - Histogram (0) | 2022.07.14 |
[KOI] 백준 21759 - 두 개의 팀 (0) | 2022.07.09 |
[KOI] 백준 2507 - 공주 구하기 (0) | 2022.06.13 |
백준 1126 - 같은 탑 (0) | 2022.06.13 |