Question meaning: input an S string and a T string, | S| > = | T|, ask to modify at least a few letters in S to make S have subsequence T
Thinking: dp + greed
f[i][j] represents the minimum number of letters to be modified for a string starting with the ith letter in S containing a string starting with the jth letter in T,
That is, the letters before i in S already contain all the letters before J in T, so continue to match from i and j respectively
The process is as follows:
S: ABCECDFF
T: BBDEC
Start i=1,j=1
In S[i], we start to look for T[j], i.e. 'B', and find it at i=2. At this time, we are faced with two choices: either let i=2 and j=1 match, or modify 'A' of i=1 to 'B', because since the modification must modify the first one
If you choose the former, then continue to match from i=3 and j=2. If you choose the latter, you will continue to match from i=2 and j=2. No matter how you choose, the sub problems you face are exactly the same as those you just faced.
For this example, to select the latter, you only need to modify 2 letters in s, and to select the former, you need to modify 3 letters in S
We need to preprocess this problem so that we can O(1) find out where the nearest 'B' is after position 1. See the code for preprocessing
We also need to record f[i][j] clearly, because there are many repeated sub problems, we do not need to repeat the calculation
Code:
#include<iostream> #include<vector> #include<algorithm> #include<cmath> #include<cstring> #include<string> #include<queue> #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; const int inf = 0x3f3f3f3f; const int maxn = 2e5+55555; const ll mod = 998244353; const double eps = 1e-7; char s[3456],t[3456]; int ne[3456][30],lens,lent; int f[3456][3456]; void init() { lens = strlen(s+1); lent = strlen(t+1); for(int i = 1;i<= 26;i++) { int last = -1; for(int j = lens;j>= 1;j--) { if(s[j]-'A'+1 == i) { last = j; } ne[j][i] = last; } } return ; } int dfs(int x,int y) { if(f[x][y]!= -1) return f[x][y]; //Has reached this state if(y == lent+1) return 0; //Finish processing the T string if(x == lens+1) return inf; //I didn'T finish processing the T string after I finished the S string int ans = inf; int pos = ne[x][t[y]-'A'+1]; //Nearest position of T[y] after x if(pos!= -1) { ans = min(ans,dfs(pos+1,y+1)); //No modification } else { ans = min(ans,dfs(x+1,y+1)+1); //modify } ans = min(ans,dfs(x+1,y+1)+1); //Modify even if it can not be modified return f[x][y] = ans; } int main() { scanf(" %s %s",s+1,t+1); init(); mem(f,-1); int ans = dfs(1,1); cout<<ans<<endl; return 0; }