Problem:
名前 (Name)
問題文
JOI 君と IOI 君は犬を飼うことにした．最初にすべきことは，犬の名前を決めることである．二人で話し合った結果，犬の名前を以下の
4
つの条件を満たすものにすることにした．
条件 1
名前は英大文字 (
A
,
B
, ...,
Z
) と英小文字 (
a
,
b
, ...,
z
) からなる文字列である．
条件 2
JOI 君の好きな文字列は長さ
N
の文字列
S
であるから，
S
が名前の部分列となるようにする．
条件 3
IOI 君の好きな文字列は長さ
M
の文字列
T
であるから，
T
が名前の部分列となるようにする．
条件 4
名前を呼びやすいものにするため，同じ文字の間には別の文字が
K
文字以上あるようにする．厳密には，位置が異なる任意の同じ文字
2
つについて，必ずその間に別の文字が
K
文字以上入っているようにする．なお，
K = 0
の場合や，名前の文字がすべて異なる場合は，この条件を満たしていると考える．
ただし，これらの条件では英大文字と英小文字は区別される．例えば
A
と
a
は異なる文字とみなされることに注意せよ．
ここで，名前の部分列とは，名前から何文字か (
0
文字でもよい) を取り除いて作れる文字列のことである．例えば，名前が
algorithm
であるとき，
ai
や
lgtm
は名前の部分列であるが，
joi
や
logarithm
は名前の部分列ではない．
二人は名前が短いほど良いと考えているため，
4
つの条件のもとで最も短い名前を付けることにした．
JOI 君と IOI 君の好きな文字列および整数
K
が与えられたとき，犬に付ける名前の文字数を求めるプログラムを作成せよ．
制約
1 ≦ N ≦ 500
．
1 ≦ M ≦ 500
．
0 ≦ K ≦ 3
．
S
は英大文字と英小文字からなる長さ
N
の文字列である．
T
は英大文字と英小文字からなる長さ
M
の文字列である．
N, M, K
は整数である．
入力
入力は以下の形式で与えられる．
N
M
K
S
T
出力
犬に付ける名前の文字数を
1
行で出力せよ．
入出力例
入力例 1
10 10 0
hottokeiki
hottokeiki
出力例 1
10
JOI 君と IOI 君の好きな文字列はどちらも
hottokeiki
である．ここで，犬の名前を
hottokeiki
にすることを考える．これは以下のように
4
つの条件を満たす．
条件 1:
名前は英大文字と英小文字からなる．
条件 2:
文字列
S
(
hottokeiki
) は犬の名前
hottokeiki
の部分列である．
条件 3:
文字列
T
(
hottokeiki
) は犬の名前
hottokeiki
の部分列である．
条件 4:
K = 0
なので，この条件は満たしている．
また，これが
4
つの条件を満たす中で最も短い名前である．この文字数
10
を出力する．
入力例 2
10 10 1
hottokeiki
hottokeiki
出力例 2
11
入力例
1
とは
K
の値のみが異なる．
もし犬の名前を入力例
1
と同じ
hottokeiki
にすれば，
条件 4
を満たさない．なぜなら，
2
つの
t
の間に文字が
1
個もないからである．
4
つの条件を満たす最も短い名前として
hotNtokeiki
などが考えられる．この文字数
11
を出力する．
入力例 3
10 10 3
hottokeiki
hottokeiki
出力例 3
15
入力例
1, 2
とは
K
の値のみが異なる．
もし犬の名前を入力例
2
と同じ
hotNtokeiki
にすれば，
条件 4
を満たさない．なぜなら，
2
つの
t
の間に
1
文字しかなく，
2
つの
k
の間に
2
文字しかなく，
2
つの
i
の間に
1
文字しかないからである．
4
つの条件を満たす最も短い名前として
hotarutokeiyuki
などが考えられる．この文字数
15
を出力する．
入力例 4
6 9 0
Jouhou
Orinpikku
出力例 4
14
JOI 君の好きな文字列は
Jouhou
，IOI 君の好きな文字列は
Orinpikku
である．ここで，犬の名前を
OJouhorinpikku
にすることを考える．これは以下のように
4
つの条件を満たす．
条件 1:
名前は英大文字と英小文字からなる．
条件 2:
文字列
S
(
Jouhou
) は犬の名前
OJouhorinpikku
の部分列である．
条件 3:
文字列
T
(
Orinpikku
) は犬の名前
OJouhorinpikku
の部分列である．
条件 4:
K = 0
なので，この条件は満たしている．
また，これが
4
つの条件を満たす中で最も短い名前のひとつである．この文字数
14
を出力する．なお，英大文字と英小文字は区別されるため，
jouhorinpikku
（文字数
13
）などは条件を満たさない．
入力例 5
9 7 1
CoMMiTTee
TeRRaCe
出力例 5
15
4
つの条件を満たす最も短い名前として
CoMaMiTeRTeRaCe
などが考えられる．この文字数
15
を出力する．
入力例 6
6 8 2
JOIIOI
JOIGEGOI
出力例 6
9
4
つの条件を満たす最も短い名前は
JOIGEIGOI
である．この文字数
9
を出力する．
情報オリンピック日本委員会
作『日本情報オリンピック第4回女性部門 本選 競技課題』

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int INF = 1000000000;
inline void chmin(int &a, int b) { if (a > b) a = b; }
int baseVals[8] = {0, 1, 4, 5, 16, 17, 20, 21};
int bitCount[8] = {0, 4, 4, 6, 4, 6, 6, 7};

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    ll N, M, K;
    cin >> N >> M >> K;
    string S, T;
    cin >> S >> T;

    int dpSize = (M + 1) * 64;
    vector<int> dp(dpSize, INF);

    int mask = (7 << (3 - K)) & 7;
    int pc2[64] = {};
    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
            int idx = baseVals[i] + baseVals[j] * 2;
            pc2[idx] = baseVals[ bitCount[i & mask] ] + baseVals[ bitCount[j & mask] ] * 2;
        }
    }
    dp[0] = 0;
    for (int posS = 0; posS <= N; posS++){
        vector<int> nDP(dpSize, INF);

        for (int posT = 0; posT <= M; posT++){
            for (int i = 63; i >= 0; i--){
                int baseIndex = posT * 64 + i / 4;
                int stateIndex = posT * 64 + i;
                chmin(dp[baseIndex], dp[stateIndex] + 1);
            }

            char cS = (posS == N ? '.' : S[posS]);
            char cT = (posT == M ? '.' : T[posT]);

            int stateS = 0;
            if (posS != N){
                for (int d = 2; d >= 0; d--){
                    if (d < posS && S[posS - 1 - d] == cS)
                        stateS |= 1 << (4 - d * 2);
                }
                for (int d = 2; d >= 0; d--){
                    if (d < posT && T[posT - 1 - d] == cS)
                        stateS |= 2 << (4 - d * 2);
                }
            }
            int stateT = 0;
            if (posT != M){
                for (int d = 2; d >= 0; d--){
                    if (d < posS && S[posS-1-d] == cT) stateT |= 1 << (4 - d * 2);
                }
                for (int d = 2; d >= 0; d--){
                    if (d < posT && T[posT-1-d] == cT) stateT |= 2 << (4 - d * 2);
                }
            }
            if (posS != N) {
                for (int i = 0; i < 64; i++){
                    if ((pc2[i] & stateS) == 0){
                        int idx = posT * 64 + i / 4 + 16;
                        chmin(nDP[idx], dp[posT * 64 + i] + 1);
                    }
                }
            }
            if (posT != M) {
                for (int i = 0; i < 64; i++){
                    if ((pc2[i] & stateT) == 0) {
                        int idx = posT * 64 + 64 + i / 4 + 32;
                        chmin(dp[idx], dp[posT * 64 + i] + 1);
                    }
                }
            }
            if (posS != N && posT != M && cS == cT) {
                for (int i = 0; i < 64; i++){
                    if ((pc2[i] & (stateT | stateS)) == 0){
                        int idx = posT * 64 + 64 + i / 4 + 48;
                        chmin(nDP[idx], dp[posT * 64 + i] + 1);
                    }
                }
            }
        }
        if (posS != N) dp.swap(nDP);
    }

    int ans = INF;
    for (int i = 0; i < 64; i++) chmin(ans, dp[M * 64 + i]);
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 3596
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
constexpr int INF = 1000000000;

// chmin: aをbで更新する（a > bのときのみ）
inline void chmin(int &a, int b) { if (a > b) a = b; }

constexpr array<int, 8> baseVals = {0, 1, 4, 5, 16, 17, 20, 21};
constexpr array<int, 8> bitCount = {0, 4, 4, 6, 4, 6, 6, 7};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    ll N, M, K;
    cin >> N >> M >> K;
    string S, T;
    cin >> S >> T;

    const int dpSize = (M + 1) * 64;
    vector<int> dp(dpSize, INF);

    int mask = (7 << (3 - K)) & 7;
    array<int, 64> pc2{};  // 0初期化

    for (int i = 0; i < 8; ++i) {
        for (int j = 0; j < 8; ++j) {
            int idx = baseVals[i] + baseVals[j] * 2;
            pc2[idx] = baseVals[bitCount[i & mask]] + baseVals[bitCount[j & mask]] * 2;
        }
    }
    dp[0] = 0;
    for (int posS = 0; posS <= N; ++posS) {
        vector<int> nDP(dpSize, INF);

        for (int posT = 0; posT <= M; ++posT) {
            for (int i = 63; i >= 0; --i) {
                int baseIndex = posT * 64 + i / 4;
                int stateIndex = posT * 64 + i;
                chmin(dp[baseIndex], dp[stateIndex] + 1);
            }

            char cS = (posS == N ? '.' : S[posS]);
            char cT = (posT == M ? '.' : T[posT]);

            int stateS = 0;
            if (posS != N) {
                for (int d = 2; d >= 0; --d) {
                    if (d < posS && S[posS - 1 - d] == cS)
                        stateS |= 1 << (4 - d * 2);
                }
                for (int d = 2; d >= 0; --d) {
                    if (d < posT && T[posT - 1 - d] == cS)
                        stateS |= 2 << (4 - d * 2);
                }
            }
            int stateT = 0;
            if (posT != M) {
                for (int d = 2; d >= 0; --d) {
                    if (d < posS && S[posS - 1 - d] == cT)
                        stateT |= 1 << (4 - d * 2);
                }
                for (int d = 2; d >= 0; --d) {
                    if (d < posT && T[posT - 1 - d] == cT)
                        stateT |= 2 << (4 - d * 2);
                }
            }
            if (posS != N) {
                for (int i = 0; i < 64; ++i) {
                    if ((pc2[i] & stateS) == 0) {
                        int idx = posT * 64 + i / 4 + 16;
                        chmin(nDP[idx], dp[posT * 64 + i] + 1);
                    }
                }
            }
            if (posT != M) {
                for (int i = 0; i < 64; ++i) {
                    if ((pc2[i] & stateT) == 0) {
                        int idx = posT * 64 + 64 + i / 4 + 32;
                        chmin(dp[idx], dp[posT * 64 + i] + 1);
                    }
                }
            }
            if (posS != N && posT != M && cS == cT) {
                for (int i = 0; i < 64; ++i) {
                    if ((pc2[i] & (stateT | stateS)) == 0) {
                        int idx = posT * 64 + 64 + i / 4 + 48;
                        chmin(nDP[idx], dp[posT * 64 + i] + 1);
                    }
                }
            }
        }
        if (posS != N) dp.swap(nDP);
    }

    int ans = INF;
    for (int i = 0; i < 64; ++i) chmin(ans, dp[M * 64 + i]);
    cout << ans << '\n';
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 3840
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
static constexpr ll INF = (ll)1e15;

// a,b のうち小さいほうで a を更新する (戻り値は更新の有無)
static inline bool chmin(ll &a, ll b) {
    if (a > b) { a = b; return true; }
    return false;
}

// DP[i][j][mask] = S の先頭 i 文字、T の先頭 j 文字をそれぞれ部分列にしつつ、
// かつ「U の末尾直前３文字の由来」を mask≡[上位２ビット:3番目, 中位２ビット:2番目, 下位２ビット:1番目]で表したときの
// 「構築可能な最短文字列長」。mask の各 2 ビットは 00=S 由来、01=T 由来、10=その他（ダミー文字 or 初期）を示す。
// 最終的には DP[N][M][*] の最小値を答とする。

static ll DP[505][505][64];

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    while (true) {
        int N, M, K;
        if (!(cin >> N >> M >> K)) return 0;
        if (N==0 && M==0 && K==0) break;
        string S, T;
        cin >> S >> T;

        // DP を無限大で初期化
        for(int i=0;i<=N;i++){
            for(int j=0;j<=M;j++){
                for(int m=0;m<64;m++){
                    DP[i][j][m] = INF;
                }
            }
        }
        // (i,j)=(0,0), mask=63 (2進数で 111111_2) → 末尾直前 3 文字すべて「その他」を示す(10 10 10_2)
        DP[0][0][63] = 0;

        // (i,j) に対して遷移を全探索
        for(int i=0;i<=N;i++){
            for(int j=0;j<=M;j++){
                if (i==N && j==M) continue;
                for(int mask=0; mask<64; mask++){
                    ll cur = DP[i][j][mask];
                    if (cur >= INF) continue;

                    // --- 遷移パターン 1: S[i] だけを U に追加する ---
                    if (i < N) {
                        // 同時に (i<M && S[i]==T[j]) の場合は「両方同時追加」に回るのでここでは skip
                        if (!(j<M && S[i]==T[j])) {
                            // 直前１文字の由来を取得 (下位２ビットで判別)
                            int prev1 = (mask >> 0) & 0b11; 
                            bool ok = true;
                            // K>0 のとき、直前１文字由来が「S 由来(00)」なら、間隔制約をチェック
                            if (K > 0 && prev1 == 0) {
                                // U の末尾１文字は S 由来なので、それが S[i-1] ということになる
                                // → S[i-1] と S[i] が同一なら間隔不足で NG
                                if (i-1 >= 0 && S[i-1] == S[i]) ok = false;
                            }
                            if (ok) {
                                ll nxt = cur + 1;
                                int ni = i+1, nj = j;
                                // S[i] が T[j] と等しければ T も一緒に進むが、ここは「S だけ」なので、
                                // もし T[j]==S[i] なら T の j も進める (ただし、先に分岐で排除しているが念のため)
                                if (j < M && S[i] == T[j]) nj = j+1;
                                // 新 mask をシフトして下位２ビットを 00 (S由来) に
                                int newMask = ((mask << 2) & 0b111111) | 0b00;
                                chmin(DP[ni][nj][newMask], nxt);
                            }
                        }
                    }

                    // --- 遷移パターン 2: T[j] だけを U に追加する ---
                    if (j < M) {
                        if (!(i<N && S[i]==T[j])) {
                            int prev1 = (mask >> 0) & 0b11;
                            bool ok = true;
                            if (K > 0 && prev1 == 1) {
                                if (j-1 >= 0 && T[j-1] == T[j]) ok = false;
                            }
                            if (ok) {
                                ll nxt = cur + 1;
                                int ni = i, nj = j+1;
                                if (i < N && S[i] == T[j]) ni = i+1;
                                int newMask = ((mask << 2) & 0b111111) | 0b01;
                                chmin(DP[ni][nj][newMask], nxt);
                            }
                        }
                    }

                    // --- 遷移パターン 3: S[i]==T[j] のとき、両方を同時に追加 ---
                    if (i<N && j<M && S[i] == T[j]) {
                        int prev1 = (mask >> 0) & 0b11;
                        bool ok = true;
                        if (K > 0 && prev1 == 0) {
                            if (i-1 >= 0 && S[i-1] == S[i]) ok = false;
                        }
                        if (ok) {
                            ll nxt = cur + 1;
                            int ni = i+1, nj = j+1;
                            int newMask = ((mask << 2) & 0b111111) | 0b00;
                            chmin(DP[ni][nj][newMask], nxt);
                        }
                    }
                }
            }
        }

        // 最終状態 (N,M) の全 mask から最小値を取る
        ll ans = INF;
        for(int m=0; m<64; m++){
            chmin(ans, DP[N][M][m]);
        }
        cout << ans << "\n";
    }
    return 0;
}
accuracy: 0.08163265306122448
time_ms: 10
memory_kb: 130512
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
static constexpr ll INF = (ll)1e15;

// chmin helper
static inline bool chmin(ll &a, ll b) {
    if (a > b) { a = b; return true; }
    return false;
}

// DP[i][j][mask] = 最短長さで、S の先頭 i 文字・T の先頭 j 文字をそれぞれ部分列に含み、
// U の末尾直前 3 文字の「由来状態」を mask (0..63) で表したときの最短名前長。
// mask の各 2 ビットは末尾直前 3 文字が どこから来たか(00=S由来、01=T由来、10=それ以外)を示す。
// たとえば、mask の下位 2 ビット=(末尾から3番目)由来、次の 2 ビット=(末尾から2番目)由来、上位 2 ビット=(末尾直前)由来。
static ll DP[505][505][64];

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N, M, K;
    while ( (cin >> N >> M >> K) ){
        string S, T;
        if (!cin || (N==0 && M==0 && K==0)) break;
        cin >> S >> T;

        // 全要素を INF で初期化
        for(int i=0;i<=N;i++){
            for(int j=0;j<=M;j++){
                for(int m=0;m<64;m++){
                    DP[i][j][m] = INF;
                }
            }
        }
        // 初期状態: (i,j)=(0,0), mask=0b111111(=63): 末尾直前に文字が無いので "10" を３つ並べて「それ以外」を示す
        DP[0][0][63] = 0;

        // すべての (i,j) を走査
        for(int i=0;i<=N;i++){
            for(int j=0;j<=M;j++){
                if (i==N && j==M) continue;
                // mask をくるくる回して遷移
                for(int mask=0; mask<64; mask++){
                    ll cur = DP[i][j][mask];
                    if (cur >= INF) continue;

                    // (1) S[i] を U に追加する
                    if (i < N) {
                        // もし S[i]==T[j] の同時追加遷移が行われる場合は飛ばす
                        if (!(j < M && S[i]==T[j])) {
                            int prev2 = (mask >> 4) & 0b11; // 直前1文字の由来
                            bool ok = true;
                            if (K>0 && prev2 == 0) {
                                // 直前由来が S なら、距離制約
                                if (i-1>=0 && S[i-1]==S[i]) ok = false;
                            }
                            if (ok){
                                ll nxt = cur + 1;
                                int ni = i+1, nj = j;
                                if (j<M && S[i]==T[j]) nj = j+1;
                                int newMask = ((mask << 2) & 0b111111) | 0b00; 
                                chmin(DP[ni][nj][newMask], nxt);
                            }
                        }
                    }

                    // (2) T[j] を U に追加する
                    if (j < M) {
                        if (!(i < N && S[i]==T[j])) {
                            int prev2 = (mask >> 4) & 0b11;
                            bool ok = true;
                            if (K>0 && prev2 == 1) {
                                if (j-1>=0 && T[j-1]==T[j]) ok = false;
                            }
                            if (ok){
                                ll nxt = cur + 1;
                                int ni = i, nj = j+1;
                                if (i<N && S[i]==T[j]) ni = i+1;
                                int newMask = ((mask << 2) & 0b111111) | 0b01;
                                chmin(DP[ni][nj][newMask], nxt);
                            }
                        }
                    }

                    // (3) S[i] == T[j] のとき、両方を同時に追加
                    if (i<N && j<M && S[i]==T[j]) {
                        int prev2 = (mask >> 4) & 0b11;
                        bool ok = true;
                        if (K>0 && prev2 == 0) {
                            if (i-1>=0 && S[i-1]==S[i]) ok = false;
                        }
                        if (ok){
                            ll nxt = cur + 1;
                            int ni = i+1, nj = j+1;
                            int newMask = ((mask << 2) & 0b111111) | 0b00;
                            chmin(DP[ni][nj][newMask], nxt);
                        }
                    }
                }
            }
        }

        // 最終状態 (N,M) の全 mask から最小値を取る
        ll answer = INF;
        for(int mask=0; mask<64; mask++){
            chmin(answer, DP[N][M][mask]);
        }
        cout << answer << "\n";
    }

    return 0;
}
accuracy: 0.08163265306122448
time_ms: 20
memory_kb: 130516
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using vvvvll = vector<vvvll>;

// 値を最小化する補助関数
bool chmin(ll &p, ll q) {
    if (p > q) {
        p = q;
        return true;
    }
    return false;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    ll N, M, K;
    cin >> N >> M >> K;
    string S, T;
    cin >> S >> T;

    // DP 配列: DP[n][m][mask] = 名前の長さの最小値
    // mask は 6 ビット (0..63) で末尾直前の 3 文字をエンコードする
    //   下位 2 ビット: 最も古い末尾文字の由来 (00=S, 01=T, 10=その他)
    //   次の 2 ビット: その次の末尾文字の由来
    //   最上位 2 ビット: 直前の末尾文字の由来
    const ll INF = (ll)1e18;
    vector< vector< vector<ll> > > DP(N + 1,
        vector< vector<ll> >(M + 1,
            vector<ll>(64, INF)));
    // 初期状態: S, T の文字をいずれもまだ使っておらず、末尾直前文字は「その他(10ビット)×3」
    DP[0][0][63] = 0;

    // 遷移
    for (ll n = 0; n <= N; ++n) {
        for (ll m = 0; m <= M; ++m) {
            // (n,m) = (N,M) は終端なので遷移不要
            if (n == N && m == M) continue;

            // mask をループして遷移
            for (int mask = 0; mask < 64; ++mask) {
                ll cur = DP[n][m][mask];
                if (cur >= INF) continue;

                // 末尾直前の 3 文字が何由来かを 2 ビットずつ参照
                // bit0-1  = 最も古い末尾文字の由来
                // bit2-3  = その次の末尾文字の由来
                // bit4-5  = 直前の末尾文字の由来

                // ■ 1. S[n] を新たに追加する (S の文字を使う)
                if (n < N) {
                    // すでに S[n]==T[m] による同時追加をしない場合
                    if (!(m < M && S[n] == T[m])) {
                        // K 文字以上隔てる制約チェック
                        // 直前文字の由来ビット = (mask >> 4) & 0b11
                        int prev2 = (mask >> 4) & 0b11;
                        bool ok = true;
                        if (K > 0 && prev2 == 0) {
                            // 直前文字が S由来 なら距離を調べる
                            // 末尾直前位置 = n-1
                            // 同じ文字かチェック
                            if (n - 1 >= 0 && S[n - 1] == S[n]) {
                                ok = false;
                            }
                        }
                        if (ok) {
                            ll nxt = cur + 1;
                            ll nn = n + 1, mm2 = m;
                            // もし S[n] == T[m] なら m も同時に進める
                            if (m < M && S[n] == T[m]) {
                                mm2 = m + 1;
                            }
                            // mask を 2 ビット左シフトして、下位 2 ビットに "S由来(00)" を入れる
                            int newMask = ((mask << 2) & 0b111111) | 0b00;
                            chmin(DP[nn][mm2][newMask], nxt);
                        }
                    }
                }

                // ■ 2. T[m] を新たに追加する (T の文字を使う)
                if (m < M) {
                    if (!(n < N && S[n] == T[m])) {
                        int prev2 = (mask >> 4) & 0b11;
                        bool ok = true;
                        if (K > 0 && prev2 == 1) {
                            if (m - 1 >= 0 && T[m - 1] == T[m]) {
                                ok = false;
                            }
                        }
                        if (ok) {
                            ll nxt = cur + 1;
                            ll nn2 = n, mm = m + 1;
                            if (n < N && S[n] == T[m]) {
                                nn2 = n + 1;
                            }
                            int newMask = ((mask << 2) & 0b111111) | 0b01;
                            chmin(DP[nn2][mm][newMask], nxt);
                        }
                    }
                }

                // ■ 3. S[n] == T[m] のとき、一度に両方を追加
                if (n < N && m < M && S[n] == T[m]) {
                    int prev2 = (mask >> 4) & 0b11;
                    bool ok = true;
                    if (K > 0 && prev2 == 0) {
                        if (n - 1 >= 0 && S[n - 1] == S[n]) {
                            ok = false;
                        }
                    }
                    if (ok) {
                        ll nxt = cur + 1;
                        ll nn = n + 1, mm = m + 1;
                        int newMask = ((mask << 2) & 0b111111) | 0b00;
                        chmin(DP[nn][mm][newMask], nxt);
                    }
                }
            } // mask ループ
        }
    }

    // 答えは DP[N][M][mask] の最小値
    ll ans = INF;
    for (int mask = 0; mask < 64; ++mask) {
        chmin(ans, DP[N][M][mask]);
    }
    cout << ans << "\n";
    return 0;
}
accuracy: 0.08163265306122448
time_ms: 40
memory_kb: 139008
final_rank: 10

code_snippet: // AOJ #789 Name
// 2025.3.7

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int INF = 1000000000;
inline void chmin(int &a, int b) { if (a > b) a = b; }
int baseVals[8] = {0, 1, 4, 5, 16, 17, 20, 21};
int bitCount[8] = {0, 4, 4, 6, 4, 6, 6, 7};

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    ll N, M, K;
    cin >> N >> M >> K;
    string S, T;
    cin >> S >> T;

    int dpSize = (M + 1) * 64;
    vector<int> dp(dpSize, INF);

    int mask = (7 << (3 - K)) & 7;
    int pc2[64] = {};
    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
            int idx = baseVals[i] + baseVals[j] * 2;
            pc2[idx] = baseVals[ bitCount[i & mask] ] + baseVals[ bitCount[j & mask] ] * 2;
        }
    }
    dp[0] = 0;
    for (int posS = 0; posS <= N; posS++){
        vector<int> nDP(dpSize, INF);

        for (int posT = 0; posT <= M; posT++){
            for (int i = 63; i >= 0; i--){
                int baseIndex = posT * 64 + i / 4;
                int stateIndex = posT * 64 + i;
                chmin(dp[baseIndex], dp[stateIndex] + 1);
            }

            char cS = (posS == N ? '.' : S[posS]);
            char cT = (posT == M ? '.' : T[posT]);

            int stateS = 0;
            if (posS != N){
                for (int d = 2; d >= 0; d--){
                    if (d < posS && S[posS - 1 - d] == cS)
                        stateS |= 1 << (4 - d * 2);
                }
                for (int d = 2; d >= 0; d--){
                    if (d < posT && T[posT - 1 - d] == cS)
                        stateS |= 2 << (4 - d * 2);
                }
            }
            int stateT = 0;
            if (posT != M){
                for (int d = 2; d >= 0; d--){
                    if (d < posS && S[posS-1-d] == cT) stateT |= 1 << (4 - d * 2);
                }
                for (int d = 2; d >= 0; d--){
                    if (d < posT && T[posT-1-d] == cT) stateT |= 2 << (4 - d * 2);
                }
            }
            if (posS != N) {
                for (int i = 0; i < 64; i++){
                    if ((pc2[i] & stateS) == 0){
                        int idx = posT * 64 + i / 4 + 16;
                        chmin(nDP[idx], dp[posT * 64 + i] + 1);
                    }
                }
            }
            if (posT != M) {
                for (int i = 0; i < 64; i++){
                    if ((pc2[i] & stateT) == 0) {
                        int idx = posT * 64 + 64 + i / 4 + 32;
                        chmin(dp[idx], dp[posT * 64 + i] + 1);
                    }
                }
            }
            if (posS != N && posT != M && cS == cT) {
                for (int i = 0; i < 64; i++){
                    if ((pc2[i] & (stateT | stateS)) == 0){
                        int idx = posT * 64 + 64 + i / 4 + 48;
                        chmin(nDP[idx], dp[posT * 64 + i] + 1);
                    }
                }
            }
        }
        if (posS != N) dp.swap(nDP);
    }

    int ans = INF;
    for (int i = 0; i < 64; i++) chmin(ans, dp[M * 64 + i]);
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 3580
final_rank: 1

code_snippet: // AOJ #789 Name
// 2025.3.7

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int INF = 1000000000;
inline void chmin(int &a, int b) { if (a > b) a = b; }
int baseVals[8] = {0, 1, 4, 5, 16, 17, 20, 21};
int bitCount[8] = {0, 4, 4, 6, 4, 6, 6, 7};

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    ll N, M, K;
    cin >> N >> M >> K;
    string S, T;
    cin >> S >> T;

    int dpSize = (M + 1) * 64;
    vector<int> dp(dpSize, INF);

    int mask = (7 << (3 - K)) & 7;
    int pc2[64] = {};
    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
            int idx = baseVals[i] + baseVals[j] * 2;
            pc2[idx] = baseVals[ bitCount[i & mask] ] + baseVals[ bitCount[j & mask] ] * 2;
        }
    }
    dp[0] = 0;
    for (int posS = 0; posS <= N; posS++){
        vector<int> nextDP(dpSize, INF);

        for (int posT = 0; posT <= M; posT++){
            for (int state = 63; state >= 0; state--){
                int baseIndex = posT * 64 + state / 4;
                int stateIndex = posT * 64 + state;
                dp[baseIndex] = min(dp[baseIndex], dp[stateIndex] + 1);
            }

            char currentCharS = (posS == N ? '.' : S[posS]);
            char currentCharT = (posT == M ? '.' : T[posT]);

            int stateS = 0;
            if (posS != N){
                for (int d = 2; d >= 0; d--){
                    if (d < posS && S[posS - 1 - d] == currentCharS)
                        stateS |= 1 << (4 - d * 2);
                }
                for (int d = 2; d >= 0; d--){
                    if (d < posT && T[posT - 1 - d] == currentCharS)
                        stateS |= 2 << (4 - d * 2);
                }
            }
            int stateT = 0;
            if (posT != M){
                for (int d = 2; d >= 0; d--){
                    if (d < posS && S[posS - 1 - d] == currentCharT)
                        stateT |= 1 << (4 - d * 2);
                }
                for (int d = 2; d >= 0; d--){
                    if (d < posT && T[posT - 1 - d] == currentCharT)
                        stateT |= 2 << (4 - d * 2);
                }
            }
            if (posS != N) {
                for (int state = 0; state < 64; state++){
                    if ((pc2[state] & stateS) == 0){
                        int idx = posT * 64 + state / 4 + 16;
                        chmin(nextDP[idx], dp[posT * 64 + state] + 1);
                    }
                }
            }
            if (posT != M) {
                for (int state = 0; state < 64; state++){
                    if ((pc2[state] & stateT) == 0) {
                        int idx = posT * 64 + 64 + state / 4 + 32;
                        chmin(dp[idx], dp[posT * 64 + state] + 1);
                    }
                }
            }
            if (posS != N && posT != M && currentCharS == currentCharT) {
                for (int state = 0; state < 64; state++){
                    if ((pc2[state] & (stateT | stateS)) == 0){
                        int idx = posT * 64 + 64 + state / 4 + 48;
                        nextDP[idx] = min(nextDP[idx], dp[posT * 64 + state] + 1);
                    }
                }
            }
        }
        if (posS != N) dp.swap(nextDP);
    }

    int ans = INF;
    for (int i = 0; i < 64; i++) chmin(ans, dp[M * 64 + i]);
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 3584
final_rank: 2

code_snippet: // AOJ #789 Name
// 2025.3.6

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    int slen, tlen, threshold;
    cin >> slen >> tlen >> threshold;

    string source, target;
    cin >> source >> target;
    source.push_back('!');
    target.push_back('?');

    vector<vector<map<string, int>>> dp(slen + 1, vector<map<string, int>>(tlen + 1));
    dp[0][0]["..."] = 0;

    int ans = numeric_limits<int>::max();

    for (int i = 0; i <= slen; ++i) {
        for (int j = 0; j <= tlen; ++j) {
            for (auto &entry : dp[i][j]) {
                string cur = entry.first;
                int currentCost = entry.second;

                if (i < slen) {
                    char sourceChar = source[i];
                    int foundIndex = find(cur.begin(), cur.end(), sourceChar) - cur.begin();
                    int additionalDots = max(threshold - foundIndex, 0);

                    string newState = cur;
                    for (int count = 0; count < additionalDots; ++count) {
                        newState = "." + newState;
                    }
                    newState = sourceChar + newState;
                    while (newState.size() > 3) newState.pop_back();

                    int newTargetIndex = j + (sourceChar == target[j] ? 1 : 0);
                    if (dp[i+1][newTargetIndex].find(newState) == dp[i+1][newTargetIndex].end())
                        dp[i+1][newTargetIndex][newState] = numeric_limits<int>::max();
                    dp[i+1][newTargetIndex][newState] = min(dp[i+1][newTargetIndex][newState],
                                                              currentCost + additionalDots + 1);
                }

                if (j < tlen) {
                    char targetChar = target[j];
                    int foundIndex = find(cur.begin(), cur.end(), targetChar) - cur.begin();
                    int additionalDots = max(threshold - foundIndex, 0);

                    string newState = cur;
                    for (int count = 0; count < additionalDots; ++count) {
                        newState = "." + newState;
                    }
                    newState = targetChar + newState;
                    while (newState.size() > 3) newState.pop_back();

                    int newSourceIndex = i + (source[i] == targetChar ? 1 : 0);
                    if (dp[newSourceIndex][j+1].find(newState) == dp[newSourceIndex][j+1].end())
                        dp[newSourceIndex][j+1][newState] = numeric_limits<int>::max();
                    dp[newSourceIndex][j+1][newState] = min(dp[newSourceIndex][j+1][newState],
                                                             currentCost + additionalDots + 1);
                }
                if (i == slen && j == tlen) ans = min(ans, currentCost);
            }
        }
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 470
memory_kb: 170884
final_rank: 7

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) { return (ull)rng() % B; }

int dp[505][505][3][3][3];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m, k;
    cin >> n >> m >> k;
    string s, t;
    cin >> s >> t;
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j <= m; j++) {
            for (int k1 = 0; k1 < 3; k1++) {
                for (int k2 = 0; k2 < 3; k2++) {
                    for (int k3 = 0; k3 < 3; k3++) {
                        dp[i][j][k1][k2][k3] = 1e9;
                    }
                }
            }
        }
    }
    dp[0][0][2][2][2] = 0;
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j <= m; j++) {
            if (i + j == n + m) continue;
            for (int k1 = 0; k1 < 3; k1++) {
                for (int k2 = 0; k2 < 3; k2++) {
                    for (int k3 = 0; k3 < 3; k3++) {
                        int val = dp[i][j][k1][k2][k3];
                        if (val == 1e9) continue;

                        if (i < n) {
                            int cost = val + 1;
                            int x = i - 1, y = j - 1;
                            string str = "";
                            if (1 <= k) {
                                if (k1 == 0) {
                                    str += s[x];
                                    if (y >= 0 and s[x] == t[y]) y -= 1;
                                    x -= 1;
                                } else if (k1 == 1) {
                                    str += t[y];
                                    if (x >= 0 and s[x] == t[y]) x -= 1;
                                    y -= 1;
                                } else {
                                    str += '.';
                                }
                            }
                            if (2 <= k) {
                                if (k2 == 0) {
                                    str += s[x];
                                    if (y >= 0 and s[x] == t[y]) y -= 1;
                                    x -= 1;
                                } else if (k2 == 1) {
                                    str += t[y];
                                    if (x >= 0 and s[x] == t[y]) x -= 1;
                                    y -= 1;
                                } else {
                                    str += '.';
                                }
                            }
                            if (3 <= k) {
                                if (k3 == 0) {
                                    str += s[x];
                                    if (y >= 0 and s[x] == t[y]) y -= 1;
                                    x -= 1;
                                } else if (k3 == 1) {
                                    str += t[y];
                                    if (x >= 0 and s[x] == t[y]) x -= 1;
                                    y -= 1;
                                } else {
                                    str += '.';
                                }
                            }

                            int a = 0, b = k1, c = k2;

                            for (int ii = 0; ii < str.size(); ii++) {
                                if (str[ii] == s[i]) {
                                    cost += k - ii;
                                    for (int l = 0; l < k - ii; l++) {
                                        c = b;
                                        b = 2;
                                    }
                                    break;
                                }
                            }

                            dp[i + 1][j + (j < m and s[i] == t[j])][a][b][c] =
                                min(dp[i + 1][j + (j < m and s[i] == t[j])][a][b][c], cost);
                        }

                        if (j < m) {
                            int cost = val + 1;
                            int x = i - 1, y = j - 1;
                            string str = "";
                            if (1 <= k) {
                                if (k1 == 0) {
                                    str += s[x];
                                    if (y >= 0 and s[x] == t[y]) y -= 1;
                                    x -= 1;
                                } else if (k1 == 1) {
                                    str += t[y];
                                    if (x >= 0 and s[x] == t[y]) x -= 1;
                                    y -= 1;
                                } else {
                                    str += '.';
                                }
                            }
                            if (2 <= k) {
                                if (k2 == 0) {
                                    str += s[x];
                                    if (y >= 0 and s[x] == t[y]) y -= 1;
                                    x -= 1;
                                } else if (k2 == 1) {
                                    str += t[y];
                                    if (x >= 0 and s[x] == t[y]) x -= 1;
                                    y -= 1;
                                } else {
                                    str += '.';
                                }
                            }
                            if (3 <= k) {
                                if (k3 == 0) {
                                    str += s[x];
                                    if (y >= 0 and s[x] == t[y]) y -= 1;
                                    x -= 1;
                                } else if (k3 == 1) {
                                    str += t[y];
                                    if (x >= 0 and s[x] == t[y]) x -= 1;
                                    y -= 1;
                                } else {
                                    str += '.';
                                }
                            }

                            int a = 1, b = k1, c = k2;

                            for (int ii = 0; ii < str.size(); ii++) {
                                if (str[ii] == t[j]) {
                                    cost += k - ii;
                                    for (int l = 0; l < k - ii; l++) {
                                        c = b;
                                        b = 2;
                                    }
                                    break;
                                }
                            }

                            dp[i + (i < n and s[i] == t[j])][j + 1][a][b][c] =
                                min(dp[i + (i < n and s[i] == t[j])][j + 1][a][b][c], cost);
                        }
                    }
                }
            }
        }
    }
    int res = 1e9;
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            for (int k = 0; k < 3; k++) {
                res = min(res, dp[n][m][i][j][k]);
            }
        }
    }
    cout << res << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 30068
final_rank: 5

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using vvvvll = vector<vvvll>;

bool chmin(ll& p, ll q) { if(p>q){
    p = min(p, q); 
    return 1;
}
return 0;};

int main() {
    ll N, M, K;
    cin >> N >> M >> K;
    string S, T;
    cin >> S >> T;
    vvvll DP(N + 1, vvll(M + 1, vll(64, 1e18)));
    DP[0][0][63] = 0;
    for (int n = 0; n <= N; n++) {
        for (int m = 0; m <= M; m++) {
            
            for (ll mm = 0; mm < 100; mm++){
                bool C=0;
                for (int b = 0; b < 64; b++) {
                if(chmin(DP[n][m][(b * 4 + 3) % 64], DP[n][m][b] + 1))C=1;
                if (DP[n][m][b] > 1e17)continue;

                if (n==3&&  m == 3) {
                    cout << "";
                }

                if (n < N && m < M && S[n] == T[m]) {
                    int bit = b;
                    int c = 5;
                    int p = 0;
                    for (int k = 0; k < 3; k++) {
                        if (bit % 4 <= 1) {
                            p++;
                            if (S[n - p] == S[n]) {
                                c = min(c, k);
                            }
                        }
                        bit /= 4;
                    }
                    p = 0;
                    bit = b;
                    for (int k = 0; k < 3; k++) {
                        if (bit % 4 == 0 || bit % 4 == 2) {
                            p++;
                            if (T[m - p] == S[n]) {
                                c = min(c, k);
                            }

                        }
                        bit /= 4;
                    }
                    if (c >= K)
                    if(chmin(DP[n + 1][m + 1][(b * 4) % 64], DP[n][m][b] + 1))C=1;
                }

                if (n < N) {
                    if (m < M && S[n] == T[m])continue;
                    int bit = b;
                    int c = 5;
                    int p = 0;
                    for (int k = 0; k < 3; k++) {
                        if (bit % 4 <= 1) {
                            p++;
                            if (S[n - p] == S[n]) {
                                c = min(c, k);
                            }
                        }
                        bit /= 4;
                    }
                    p = 0;
                    bit = b;
                    for (int k = 0; k < 3; k++) {
                        if (bit % 4 == 0 || bit % 4 == 2) {
                            p++;
                            if (T[m - p] == S[n]) {
                                c = min(c, k);
                            }

                        }
                        bit /= 4;
                    }
                    if (c >= K)
                    if(chmin(DP[n + 1][m][(b * 4 + 1) % 64], DP[n][m][b] + 1))C=1;
                }
                if (m < M) {
                    if (n < N && S[n] == T[m])continue;
                    int bit = b;
                    int c = 5;
                    int p = 0;
                    for (int k = 0; k < 3; k++) {
                        if (bit % 4 <= 1) {
                            p++;
                            if (S[n - p] == T[m]) {
                                c = min(c, k);
                            }
                        }
                        bit /= 4;
                    }
                    p = 0;
                    bit = b;
                    for (int k = 0; k < 3; k++) {
                        if (bit % 4 == 0 || bit % 4 == 2) {
                            p++;
                            if (T[m - p] == T[m]) {
                                c = min(c, k);
                            }

                        }
                        bit /= 4;
                    }
                    if (c >= K)
                    if(chmin(DP[n][m + 1][(b * 4 + 2) % 64], DP[n][m][b] + 1))C=1;
                }
                }
                if(C==0)break;
            }
        }
    }
    ll an = 1e18;
    for (int i = 0; i < 64; i++)chmin(an, DP[N][M][i]);
    cout << an << endl;
}
accuracy: 1
time_ms: 290
memory_kb: 138768
final_rank: 6