Recover the Special Letter
Autumn Tournament (2025)
Submission name: special.cpp
Problem summary
Exactly one character of S was changed to a different letter, then arbitrary letters were inserted to form P. Recover any valid1-based changed position and replacement letter.
Input
Strings S and P on separate lines.
Output
A1-based position in S and the different replacement letter.
Constraints
1 ≤ |S| ≤ |P| ≤ 1000000; lowercase Latin letters; at least one solution exists.
Worked example
Original statement sample; constructive output may differ when any valid answer is accepted.
Input
aaabaaa aaacaaa
Output
4 c
Solution analysis
- Greedily match every prefix of S as early as possible in P. Store left[i], the earliest P position where the prefix before S[i] finishes; use−1 for the empty prefix. Independently match suffixes backward, storing right[i+1], the latest position where the suffix after S[i] can start.
- Changing position i works exactly when a letter different from S[i] exists strictly between those two boundaries. There is no need to scan that gap repeatedly: precompute nextDifferent[j], the next index after j whose character differs from P[j]. For a gap beginning at j, either P[j] already differs or nextDifferent[j] is its first differing candidate.
- For S=aaabaaa and P=aaacaaa, the prefix aaa ends at index2 and the suffix aaa starts at index4. The one-position gap contains c, which differs from b, so the answer is4 c. The prefix/suffix scans are linear even when many equal letters repeat.
Why it works
Any embedding after changing S[i] has its preceding prefix no earlier than the greedy earliest prefix endpoint and its suffix no later than the greedy latest suffix start. Thus its changed character must fit in the computed gap. Conversely, a different character in that gap joins the two greedy embeddings into a valid result. Testing all positions therefore finds a promised solution.
Watch out. The replacement must differ from the original letter even if S already is a subsequence of P. Require valid prefix and suffix embeddings before using a gap. Print the S position, not the index in P.
Commented C++17 solution
An independently written complete program with standard headers.
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
string source,result;
cin>>source>>result;
int n=static_cast<int>(source.size());
int m=static_cast<int>(result.size());
vector<int>left(n+1,m);
vector<int>right(n+1,-1);
left[0]=-1;
int position=0;
for(int i=0;i<n;i++){
while(position<m&&result[position]!=source[i]){
position++;
}
if(position==m){
break;
}
left[i+1]=position++;
}
right[n]=m;
position=m-1;
for(int i=n-1;i>=0;i--){
while(position>=0&&result[position]!=source[i]){
position--;
}
if(position<0){
break;
}
right[i]=position--;
}
// Skip a whole equal-letter run when looking for a changed character.
vector<int>nextDifferent(m,m);
for(int i=m-2;i>=0;i--){
nextDifferent[i]=result[i+1]!=result[i]?i+1:nextDifferent[i+1];
}
for(int i=0;i<n;i++){
if(left[i]==m||right[i+1]==-1){
continue;
}
int candidate=left[i]+1;
if(candidate<right[i+1]&&result[candidate]==source[i]){
candidate=nextDifferent[candidate];
}
if(candidate<right[i+1]){
cout<<i+1<<' '<<result[candidate]<<'\n';
return 0;
}
}
}