Official

F - More ABC Editorial by en_translator


Let \(S_i\) denote the \(i\)-th character of \(S\) \((1\leq i\leq \lvert S\rvert)\), and \(S_i\ldots S_j\) denote the substring formed by the \(i\)-th through \(j\)-th characters of \(S\).
Also, for a string \(T\), let \(f(T)\) be the number of occurrences of ABC in \(T\).
Additionally, let \(S\) denote the string before Takahashi applies the operation (that is, the string given as the input), and distinguish it from the result of replacements, \(S'\).

Consider solving this problem with Dynamic Programming (DP).
Let \(dp[i][j]\) \((0\leq i\leq N,0\leq j\leq K)\) be the minimum number of characters that need to be replaced so that \(S'_1\ldots S'_i\) contains at least \(j\) more occurrences of ABC than \(S_1\ldots S_i\), or \(+\infty\) if it is impossible.

The initial states are \(dp[i][0]=0\) \((0\leq i\leq N)\) and \(dp[0][j]=\infty\) \((1\leq j\leq K)\), and the sought answer is \(dp[N][K]\).
Here, we have \(dp[i][j]>0=dp[i][0]\) for \(j<0\) and \(dp[i][j]>dp[i][K]\geq dp[N][K]\) for \(j>K\); these states do not lead to \(dp[N][K]\) optimally, and can be safely ignored, because

  • in optimal transitions, the values always increase monotonically, and
  • \(dp[i][j]\) is only affected by \(dp[i+1][j-1],dp[i+1][j],dp[i+3][j]\), and \(dp[i+3][j+1]\).

The transitions into \(dp[i][j]\) \((1\leq i\leq N, 1\leq j\leq K)\) are exhausted by the following two cases:

  • where \(S'_{i-2}S'_{i-1}S'_i=\)ABC does hold
  • where \(S'_{i-2}S'_{i-1}S'_i=\)ABC does not hold

Note that if \(i<3\) in particular, only the latter need to be take into account.
Let us consider how many characters need to be updated for each case.

\(1\). If \(S'_{i-2}S'_{i-1}S'_i=\)ABC does hold

In this case, \(f(S'_1S'_2\ldots S'_i)=f(S'_1S'_2\ldots S'_{i-3})+1\).
Thus, \(f(S'_1S'_2\ldots S'_{i-3})-f(S_1S_2\ldots S_{i-3})=f(S'_1S'_2\ldots S'_i)-1-f(S_1S_2\ldots S_i)+\{f(S_1S_2\ldots S_i)-f(S_1S_2\ldots S_{i-3})\}=j-1+\{f(S_1S_2\ldots S_i)-f(S_1S_2\ldots S_{i-3})\}\),
so if we define \(X_i\) as \(f(S_1S_2\ldots S_i)-f(S_1S_2\ldots S_{i-3})\) \((0\leq X_i\leq 1)\) and \(Y_i\) as the minimum number of characters we need to modify to turn \(S_{i-2}S_{i-1}S_i\) into ABC \((0\leq Y_i\leq 3)\), the minimum number of characters to be modified in this case turns out to be \(dp[i-3][j-1+X_i]+Y_i\).

\(2\). If \(S'_{i-2}S'_{i-1}S'_i=\)ABC does not hold

For this case, we may safely assume that \(S'_i\) is not modified, for the following reason. Suppose \(S'_i\) is modified but \(S'_{i-2}S'_{i-1}S'_i=\)ABC does not hold. Then for \(S'_1S'_2\ldots S'_{i-1}\bm{S'_i}\) and \(S'_1S'_2\ldots S'_{i-1}\bm{S_i}\), we have \(f(S'_1S'_2\ldots S'_{i-1}S'_i)\leq f(S'_1S'_2\ldots S'_{i-1}S_i)\) and the latter has fewer modified characters, so one can obtain the same number of ABCs by modifying fewer characters than we obtain \(S'_1S'_2\ldots S'_{i-1}S'_i\), which is a contradiction.

In this case, \(f(S'_1S'_2\ldots S'_i)=f(S'_1S'_2\ldots S'_{i-1})\), and just as in case \(1\)., \(f(S'_1S'_2\ldots S'_{i-1})-f(S_1S_2\ldots S_{i-1})=j+\{f(S_1S_2\ldots S_i)-f(S_1S_2\ldots S_{i-3})\}\). So if we define \(Z_i\) as \(f(S_1S_2\ldots S_i)-f(S_1S_2\ldots S_{i-1})\) \((0\leq Z_i\leq 1)\), the minimum number of characters to be modified in this case turns out to be \(dp[i-1][j+Z_i]\).

Hence, \(dp[i][j]=\min(dp[i-3][j-1+X_i]+Y_i,dp[i-1][j+Z_i])\). If either references out of array bounds, the other argument is adopted. Note that it is impossible that both are out of bounds, because if \(Z_i=1\) then \(i\geq 3\).

\(Z_i\) is \(1\) if \(S_{i-2}S_{i-1}S_i=\) ABC and \(0\) otherwise, and \(X_i=Z_{i-2}+Z_{i-1}+Z_i\), so these can be computed in constant time for each \(i\); \(Y_i\) can also be found in constant time per \(i\).

The transitions can be processed in \(O(1)\) too, so the answer can be found in a total of \(O(NK)\) time.
Hence, the problem has been solved.

Sample code in C++:

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

#define INF (int)1e+9

int main() {
	int t,n,k;
	string s;

	cin>>t;
	for(int itest=0;itest<t;itest++){
		cin>>s;
		cin>>k;
		n=s.size();

		vector<int>x(n+1),y(n+1),z(n+1);
		vector<vector<int> >dp(n+1,vector<int>(k+1));

		for(int i=3;i<=n;i++){
			if(s[i-3]!='A')y[i]++;
			if(s[i-2]!='B')y[i]++;
			if(s[i-1]!='C')y[i]++;
			if(y[i]==0)z[i]++;
			for(int j=0;j<3;j++){
				if(i+j<=n)x[i+j]+=z[i];
			}
		}

		for(int j=1;j<=k;j++)dp[0][j]=INF;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=k;j++){
				dp[i][j]=INF;
				if(j+z[i]<=k)dp[i][j]=min(dp[i][j],dp[i-1][j+z[i]]);
				if(i>=3)dp[i][j]=min(dp[i][j],dp[i-3][j-1+x[i]]+y[i]);
			}
		}
		if(dp[n][k]>=INF)cout<<-1<<endl;
		else cout<<dp[n][k]<<endl;
	}
	return 0;
}

posted:
last update: