公式
E - ダンスの同期 / Dance Synchronization 解説
by
E - ダンスの同期 / Dance Synchronization 解説
by
kyopro_friends
まず修正を行わない場合を考えます。
ペアの個数の最大値は、\(s,t\) の LCS (最長共通部分列) の長さになります。これは \(\mathrm{DP}[i][j]\) を「 \(s\) の \(i\) 文字目までからなる文字列と、 \(t\) の \(j\) 文字目までからなる文字列の LCS の長さ」と定める動的計画法により \(O(|s||t|)\) で求めることができます。
修正を行う場合を考えます。
\(s\) には同じ文字が \(3\) 回以上連続する箇所が存在しないことから、\(s\) の先頭でも末尾でもない文字を変更することはできません。\(t\) も同様なので、「\(s,t\) の先頭・末尾をそれぞれ変更するかどうか」の \(2^4\) 通りについて実際に LCS を求めることでこの問題を \(O(|s||t|)\) で解くことができます。
実装例 (C++)
#include<bits/stdc++.h>
using namespace std;
int main(){
string sss, ttt;
int k;
cin >> sss >> ttt >> k;
int n = sss.size(), m = ttt.size();
vector<int> ss, tt;
for(int i=0; i<n; i++){
ss.push_back(sss[i] - '0');
}
for(int i=0; i<m; i++){
tt.push_back(ttt[i] - '0');
}
auto lcs=[](vector<int> s, vector<int> t){
int n=s.size();
int m=t.size();
vector<vector<int>>dp(n+1,vector<int>(m+1));
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
dp[i+1][j+1] = max(dp[i+1][j+1], dp[i][j+1]);
dp[i+1][j+1] = max(dp[i+1][j+1], dp[i+1][j]);
if(s[i] == t[j]){
dp[i+1][j+1] = max(dp[i+1][j+1], dp[i][j]+1);
}
}
}
return dp[n][m];
};
int ans = 0;
for(int s1=0; s1<2; s1++){
for(int s2=0; s2<2; s2++){
for(int t1=0; t1<2; t1++){
for(int t2=0; t2<2; t2++){
if(s1 + s2 + t1 + t2 > k){
continue;
}
vector<int> s = ss, t = tt;
if(s1 && (s.size()==1 || s[0]==s[1])){
s[0] ^= 1;
}
if(s2 && (s.size()==1 || s[n-1]==s[n-2])){
s[n-1] ^= 1;
}
if(t1 && (t.size()==1 || t[0]==t[1])){
t[0] ^= 1;
}
if(t2 && (t.size()==1 || t[m-1]==t[m-2])){
t[m-1] ^= 1;
}
ans = max(ans, lcs(s, t));
}
}
}
}
cout << ans << endl;
}
実装例 (Python)
SS = list(map(int, input()))
TT = list(map(int, input()))
K = int(input())
def lcs(S, T):
N = len(S)
M = len(T)
dp = [[0]*(M+1) for _ in range(N+1)]
for i in range(N):
for j in range(M):
dp[i+1][j+1] = max(dp[i+1][j+1], dp[i][j+1])
dp[i+1][j+1] = max(dp[i+1][j+1], dp[i+1][j])
if S[i] == T[j]:
dp[i+1][j+1] = max(dp[i+1][j+1], dp[i][j]+1)
return dp[N][M]
ans = 0
for s1 in range(2):
for s2 in range(2):
for t1 in range(2):
for t2 in range(2):
if s1 + s2 + t1 + t2 > K:
continue
S = list(SS)
T = list(TT)
if s1 and (len(S)==1 or S[0]==S[1]):
S[0] ^= 1
if s2 and (len(S)==1 or S[-1]==S[-2]):
S[-1] ^= 1
if t1 and (len(T)==1 or T[0]==T[1]):
T[0] ^= 1
if t2 and (len(T)==1 or T[-1]==T[-2]):
T[-1] ^= 1
ans = max(ans, lcs(S, T))
print(ans)
投稿日時:
最終更新:
