Official

F - Operate 1 Editorial by en_translator


This editorial is specific to Problem C. See also the editorial for Problem F, which handles more general cases.


The answer is obviously Yes if \(S=T\), so we consider the other cases and assume that the operation was performed exactly once.

The operation was either a modification, insertion, or removal.
First, let us try to solve the problem assuming that we know which operation has been performed.

If “modification” was performed

If a modification was performed once, then \(S\) and \(T\) should have the same length, with different characters at only one position.
This can be checked by a loop.

If “insertion” was performed

If an insertion was performed once, one can remove one character of \(T\) to match it with \(S\).
However, if we try to exhaustively search the inserted position, the time complexity will be \(O(|S|^2)\), not fitting to the execution time limit. How can we optimize it?
There are several ways; we will introduce one of them.

  • Let \(p\) be the maximum number of characters for which the initial characters of \(S\) and \(T\) coincide.
  • Let \(s\) be the maximum number of characters for which the final characters of \(S\) and \(T\) coincide.
  • If \(p+s \ge |S|\), one can insert one character to \(S\) to obtain \(T\).

More intuitively, if one can split \(S\) into two parts, and use them up as the initial and final characters of \(T\), then one can insert one character to \(S\) to obtain \(T\). This can be checked in \(O(|S|)\) time.

If “removal” was performed

In this case, we need to check whether one can insert one character to \(T\) to obtain \(S\); this is equivalent to the “insertion” case.

We have now figured out the solution when the kind of operation that has been performed is known.
Actually, the kind of operation that has been performed can be identified easily. How can we do that?

One can find the kind of operation that may have been performed as follows.
The key is the changes in the length of the string when each operation is performed.

  • If \(|S| = |T|\), only “modification” may have been performed.
  • If \(|S|+1 = |T|\), only “insertion” may have been performed.
  • If \(|S|-1 = |T|\), only “removal” may have been performed.
  • If none of the above is satisfied, \(S\) cannot be matched with \(T\) in one operation.

By implementing this, the problem can be solved in a total of \(O(|S|)\) time.

Sample code (C++):

#include<bits/stdc++.h>

using namespace std;

int main(){
  int k;
  string s,t;
  cin >> k >> s >> t;
  if(s==t){
    cout << "Yes\n";
    return 0;
  }

  int sl=s.size();
  int tl=t.size();

  if(sl==tl){
    // modify
    int c=0;
    for(int i=0;i<sl;i++){
      if(s[i]!=t[i]){c++;}
    }
    if(c<=1){cout << "Yes\n";}
    else{cout << "No\n";}
  }
  else if(sl+1==tl){
    // insert
    int pc=0,sc=0;
    while(pc<sl){
      if(s[pc]==t[pc]){pc++;}
      else{break;}
    }
    while(sc<sl){
      if(s[sl-1-sc]==t[tl-1-sc]){sc++;}
      else{break;}
    }
    if(pc+sc>=sl){cout << "Yes\n";}
    else{cout << "No\n";}
  }
  else if(sl-1==tl){
    // erase
    swap(s,t);
    swap(sl,tl);
    int pc=0,sc=0;
    while(pc<sl){
      if(s[pc]==t[pc]){pc++;}
      else{break;}
    }
    while(sc<sl){
      if(s[sl-1-sc]==t[tl-1-sc]){sc++;}
      else{break;}
    }
    if(pc+sc>=sl){cout << "Yes\n";}
    else{cout << "No\n";}
  }
  else{
    cout << "No\n";
  }
  return 0;
}

posted:
last update: