An edit between two strings is one of the following changes.
- Add a character
- Delete a character
- Change a character
Given two strings s1 and s2, find if s1 can be converted to s2 with exactly one edit.
Note: Even if the strings are already equal, one edit operation can still be considered valid by "changing" a character to the same character at any index, satisfying the condition of exactly one edit.
Examples:
Input: s1 = "geek", s2 = "geeks"
Output: Yes
Explanation: Appending 's' to string s1 will make s1 equal to s2.Input: s1 = "geeks", s2 = "geeks"
Output: Yes
Explanation: s1 and s2 are already equal. Change any character to itself.Input: s1 = "peaks", s2 = "geeks"
Output: No
Explanation: Minimum edits required are 2.
[Naive Approach] Using Dynamic Programming - O(n * m) time and O(n * m) space
The idea is to calculate the minimum number of edits required to make strings s1 and s2 equal using dynamic programming. If the minimum edits is less than equal to 1, return true. Otherwise return false.
Refer to Edit Distance for detailed explanation.
// C++ program to check if given two strings are
// at distance one.
#include <bits/stdc++.h>
using namespace std;
// Function to calculate the edit distance
// between two strings.
int editDistance(string &s1, string &s2) {
int m = s1.length();
int n = s2.length();
// Create a table to store results of subproblems
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
// Fill the known entries in dp[][]
// If one string is empty, then answer
// is length of the other string
for (int i = 0; i <= m; i++)
dp[i][0] = i;
for (int j = 0; j <= n; j++)
dp[0][j] = j;
// Fill the rest of dp[][]
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (s1[i - 1] == s2[j - 1])
dp[i][j] = dp[i - 1][j - 1];
else
dp[i][j] = 1 + min({dp[i][j - 1],
dp[i - 1][j],
dp[i - 1][j - 1]});
}
}
return dp[m][n];
}
// Returns true if edit distance between s1 and
// s2 is one, else false
bool isEditDistanceOne(string s1, string s2) {
int count = editDistance(s1, s2);
return count <= 1;
}
int main() {
string s1 = "geek";
string s2 = "geeks";
if (isEditDistanceOne(s1, s2)) {
cout << "Yes" << endl;
}
else {
cout << "No" << endl;
}
return 0;
}
// Java program to check if given two strings are
// at distance one.
class GfG {
// Function to calculate the edit distance
// between two strings.
static int editDistance(String s1, String s2) {
int m = s1.length();
int n = s2.length();
// Create a table to store results of subproblems
int[][] dp = new int[m + 1][n + 1];
// Fill the known entries in dp[][]
// If one string is empty, then answer
// is length of the other string
for (int i = 0; i <= m; i++)
dp[i][0] = i;
for (int j = 0; j <= n; j++)
dp[0][j] = j;
// Fill the rest of dp[][]
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (s1.charAt(i - 1) == s2.charAt(j - 1))
dp[i][j] = dp[i - 1][j - 1];
else
dp[i][j] = 1 + Math.min(
Math.min(dp[i][j - 1], dp[i - 1][j]),
dp[i - 1][j - 1]
);
}
}
return dp[m][n];
}
// Returns true if edit distance between s1 and
// s2 is one, else false
static boolean isEditDistanceOne(String s1, String s2) {
int count = editDistance(s1, s2);
return count <= 1;
}
public static void main(String[] args) {
String s1 = "geek";
String s2 = "geeks";
if (isEditDistanceOne(s1, s2)) {
System.out.println("Yes");
}
else {
System.out.println("No");
}
}
}
# Python program to check if given two strings are
# at distance one.
# Function to calculate the edit distance
# between two strings.
def editDistance(s1, s2):
m = len(s1)
n = len(s2)
# Create a table to store results of subproblems
dp = [[0] * (n + 1) for _ in range(m + 1)]
# Fill the known entries in dp[][]
# If one string is empty, then answer
# is length of the other string
for i in range(m + 1):
dp[i][0] = i
for j in range(n + 1):
dp[0][j] = j
# Fill the rest of dp[][]
for i in range(1, m + 1):
for j in range(1, n + 1):
if s1[i - 1] == s2[j - 1]:
dp[i][j] = dp[i - 1][j - 1]
else:
dp[i][j] = 1 + min(
dp[i][j - 1],
dp[i - 1][j],
dp[i - 1][j - 1]
)
return dp[m][n]
# Returns true if edit distance between s1 and
# s2 is one, else false
def isEditDistanceOne(s1, s2):
count = editDistance(s1, s2)
return count <= 1
if __name__ == "__main__":
s1 = "geek"
s2 = "geeks"
if isEditDistanceOne(s1, s2):
print("Yes")
else:
print("No")
// C# program to check if given two strings are
// at distance one.
using System;
class GfG {
// Function to calculate the edit distance
// between two strings.
static int editDistance(string s1, string s2) {
int m = s1.Length;
int n = s2.Length;
// Create a table to store results of subproblems
int[,] dp = new int[m + 1, n + 1];
// Fill the known entries in dp[][]
// If one string is empty, then answer
// is length of the other string
for (int i = 0; i <= m; i++)
dp[i, 0] = i;
for (int j = 0; j <= n; j++)
dp[0, j] = j;
// Fill the rest of dp[][]
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (s1[i - 1] == s2[j - 1])
dp[i, j] = dp[i - 1, j - 1];
else
dp[i, j] = 1 + Math.Min(
Math.Min(dp[i, j - 1], dp[i - 1, j]),
dp[i - 1, j - 1]
);
}
}
return dp[m, n];
}
// Returns true if edit distance between s1 and
// s2 is one, else false
static bool isEditDistanceOne(string s1, string s2) {
int count = editDistance(s1, s2);
return count <= 1;
}
static void Main(string[] args) {
string s1 = "geek";
string s2 = "geeks";
if (isEditDistanceOne(s1, s2)) {
Console.WriteLine("Yes");
}
else {
Console.WriteLine("No");
}
}
}
// JavaScript program to check if given two strings are
// at distance one.
// Function to calculate the edit distance
// between two strings.
function editDistance(s1, s2) {
let m = s1.length;
let n = s2.length;
// Create a table to store results of subproblems
let dp = new Array(m + 1);
for (let i = 0; i <= m; i++) {
dp[i] = new Array(n + 1).fill(0);
}
// Fill the known entries in dp[][]
// If one string is empty, then answer
// is length of the other string
for (let i = 0; i <= m; i++)
dp[i][0] = i;
for (let j = 0; j <= n; j++)
dp[0][j] = j;
// Fill the rest of dp[][]
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
if (s1[i - 1] === s2[j - 1])
dp[i][j] = dp[i - 1][j - 1];
else
dp[i][j] = 1 + Math.min(
dp[i][j - 1],
dp[i - 1][j],
dp[i - 1][j - 1]
);
}
}
return dp[m][n];
}
// Returns true if edit distance between s1 and
// s2 is one, else false
function isEditDistanceOne(s1, s2) {
let count = editDistance(s1, s2);
return count <= 1;
}
let s1 = "geek";
let s2 = "geeks";
if (isEditDistanceOne(s1, s2)) {
console.log("Yes");
}
else {
console.log("No");
}
Output
Yes
[Expected Approach] Using Method - O(n + m) time and O(1) Space
The idea is based on the following observations.
- Lengths of both strings differ at most by one.
- If length of s1 is one less, then the only possible operation is insert.
- If length of s1 is one more, then the only possibility is delete.
We simultaneously traverse through both strings. If the current character match, then we move ahead in both strings. If do not match, then we compare the lengths. If lengths are same, then it is a possible case of mismatch, we move ahead in both strings. If length of the first string is less, then it is a possible case of insert, we move ahead in the first string. If length of the first string is more, then possible case of delete, so we move ahead in the first string.
// C++ program to check if given two strings are
// at distance one.
#include <bits/stdc++.h>
using namespace std;
// Returns true if edit distance between s1 and
// s2 is one, else false
bool isEditDistanceOne(string s1, string s2) {
// Find lengths of given strings
int m = s1.length(), n = s2.length();
// If difference between lengths is more than
// 1, then strings can't be at one distance
if (abs(m - n) > 1)
return false;
// Count of edits
int count = 0;
int i = 0, j = 0;
while (i < m && j < n) {
// If current characters don't match
if (s1[i] != s2[j]) {
// If one edit has been done already
if (count == 1)
return false;
// If length of one string is
// more, then only possible edit
// is to remove a character
if (m > n)
i++;
else if (m< n)
j++;
// If lengths of both strings is same,
// we can change the character in
// either string
else {
i++;
j++;
}
// Increment count of edits
count++;
}
// If current characters match
else {
i++;
j++;
}
}
// If last character is extra in any string
if (i < m || j < n)
count++;
return count <= 1;
}
int main() {
string s1 = "geek";
string s2 = "geeks";
if (isEditDistanceOne(s1, s2)) {
cout << "Yes" << endl;
}
else {
cout << "No" << endl;
}
return 0;
}
// Java program to check if given two strings are
// at distance one.
class GfG {
// Returns true if edit distance between s1 and
// s2 is one, else false
static boolean isEditDistanceOne(String s1, String s2) {
// Find lengths of given strings
int m = s1.length(), n = s2.length();
// If difference between lengths is more than
// 1, then strings can't be at one distance
if (Math.abs(m - n) > 1)
return false;
// Count of edits
int count = 0;
int i = 0, j = 0;
while (i < m && j < n) {
// If current characters don't match
if (s1.charAt(i) != s2.charAt(j)) {
// If one edit has been done already
if (count == 1)
return false;
// If length of one string is
// more, then only possible edit
// is to remove a character
if (m > n)
i++;
else if (m < n)
j++;
// If lengths of both strings is same,
// we can change the character in
// either string
else {
i++;
j++;
}
// Increment count of edits
count++;
}
// If current characters match
else {
i++;
j++;
}
}
// If last character is extra in any string
if (i < m || j < n)
count++;
return count <= 1;
}
public static void main(String[] args) {
String s1 = "geek";
String s2 = "geeks";
if (isEditDistanceOne(s1, s2)) {
System.out.println("Yes");
} else {
System.out.println("No");
}
}
}
# Python program to check if given two strings are
# at distance one.
# Returns true if edit distance between s1 and
# s2 is one, else false
def isEditDistanceOne(s1, s2):
# Find lengths of given strings
m, n = len(s1), len(s2)
# If difference between lengths is more than
# 1, then strings can't be at one distance
if abs(m - n) > 1:
return False
# Count of edits
count = 0
i, j = 0, 0
while i < m and j < n:
# If current characters don't match
if s1[i] != s2[j]:
# If one edit has been done already
if count == 1:
return False
# If length of one string is
# more, then only possible edit
# is to remove a character
if m > n:
i += 1
elif m < n:
j += 1
# If lengths of both strings is same,
# we can change the character in
# either string
else:
i += 1
j += 1
# Increment count of edits
count += 1
# If current characters match
else:
i += 1
j += 1
# If last character is extra in any string
if i < m or j < n:
count += 1
return count <= 1
if __name__ == "__main__":
s1 = "geek"
s2 = "geeks"
if isEditDistanceOne(s1, s2):
print("Yes")
else:
print("No")
// C# program to check if given two strings are
// at distance one.
using System;
class GfG {
// Returns true if edit distance between s1 and
// s2 is one, else false
static bool isEditDistanceOne(string s1, string s2) {
// Find lengths of given strings
int m = s1.Length, n = s2.Length;
// If difference between lengths is more than
// 1, then strings can't be at one distance
if (Math.Abs(m - n) > 1)
return false;
// Count of edits
int count = 0;
int i = 0, j = 0;
while (i < m && j < n) {
// If current characters don't match
if (s1[i] != s2[j]) {
// If one edit has been done already
if (count == 1)
return false;
// If length of one string is
// more, then only possible edit
// is to remove a character
if (m > n)
i++;
else if (m < n)
j++;
// If lengths of both strings is same,
// we can change the character in
// either string
else {
i++;
j++;
}
// Increment count of edits
count++;
}
// If current characters match
else {
i++;
j++;
}
}
// If last character is extra in any string
if (i < m || j < n)
count++;
return count <= 1;
}
static void Main() {
string s1 = "geek";
string s2 = "geeks";
if (isEditDistanceOne(s1, s2)) {
Console.WriteLine("Yes");
} else {
Console.WriteLine("No");
}
}
}
// JavaScript program to check if given two strings are
// at distance one.
// Returns true if edit distance between s1 and
// s2 is one, else false
function isEditDistanceOne(s1, s2) {
// Find lengths of given strings
let m = s1.length, n = s2.length;
// If difference between lengths is more than
// 1, then strings can't be at one distance
if (Math.abs(m - n) > 1)
return false;
// Count of edits
let count = 0;
let i = 0, j = 0;
while (i < m && j < n) {
// If current characters don't match
if (s1[i] !== s2[j]) {
// If one edit has been done already
if (count === 1)
return false;
// If length of one string is
// more, then only possible edit
// is to remove a character
if (m > n)
i++;
else if (m < n)
j++;
else {
i++;
j++;
}
// Increment count of edits
count++;
}
// If current characters match
else {
i++;
j++;
}
}
// If last character is extra in any string
if (i < m || j < n)
count++;
return count <= 1;
}
let s1 = "geek";
let s2 = "geeks";
if (isEditDistanceOne(s1, s2)) {
console.log("Yes");
} else {
console.log("No");
}
Output
Yes