The sixth question of the final of group B of the 10th Blue Bridge Cup in 2019

Keywords: Programming

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;
}

 

Posted by quark76 on Sun, 03 Nov 2019 10:49:40 -0800