Check if edit distance between two strings is one
Last Updated :
27 Nov, 2023
An edit between two strings is one of the following changes.
- Add a character
- Delete a character
- Change a character
Given two string s1 and s2, find if s1 can be converted to s2 with exactly one edit. Expected time complexity is O(m+n) where m and n are lengths of two strings.
Examples:
Input: s1 = "geeks", s2 = "geek"
Output: yes
Number of edits is 1
Input: s1 = "geeks", s2 = "geeks"
Output: no
Number of edits is 0
Input: s1 = "geaks", s2 = "geeks"
Output: yes
Number of edits is 1
Input: s1 = "peaks", s2 = "geeks"
Output: no
Number of edits is 2
A Simple Solution is to find Edit Distance using Dynamic programming. If distance is 1, then return true, else return false. Time complexity of this solution is O(n2)
An Efficient Solution is to simultaneously traverse both strings and keep track of count of different characters. Below is complete algorithm.
Let the input strings be s1 and s2 and lengths of input
strings be m and n respectively.
1) If difference between m an n is more than 1,
return false.
2) Initialize count of edits as 0.
3) Start traversing both strings from first character.
a) If current characters don't match, then
(i) Increment count of edits
(ii) If count becomes more than 1, return false
(iii) If length of one string is more, then only
possible edit is to remove a character.
Therefore, move ahead in larger string.
(iv) If length is same, then only possible edit
is to change a character. Therefore, move
ahead in both strings.
b) Else, move ahead in both strings.
Below is the implementation of the above idea :
C++
#include <bits/stdc++.h>
using namespace std;
bool isEditDistanceOne(string s1, string s2)
{
int m = s1.length(), n = s2.length();
if ( abs (m - n) > 1)
return false ;
int count = 0;
int i = 0, j = 0;
while (i < m && j < n)
{
if (s1[i] != s2[j])
{
if (count == 1)
return false ;
if (m > n)
i++;
else if (m< n)
j++;
else
{
i++;
j++;
}
count++;
}
else
{
i++;
j++;
}
}
if (i < m || j < n)
count++;
return count == 1;
}
int main()
{
string s1 = "gfg" ;
string s2 = "gf" ;
isEditDistanceOne(s1, s2)?
cout << "Yes" : cout << "No" ;
return 0;
}
|
Java
class GFG
{
static boolean isEditDistanceOne(String s1,
String s2)
{
int m = s1.length(), n = s2.length();
if (Math.abs(m - n) > 1 )
return false ;
int count = 0 ;
int i = 0 , j = 0 ;
while (i < m && j < n)
{
if (s1.charAt(i) != s2.charAt(j))
{
if (count == 1 )
return false ;
if (m > n)
i++;
else if (m< n)
j++;
else
{
i++;
j++;
}
count++;
}
else
{
i++;
j++;
}
}
if (i < m || j < n)
count++;
return count == 1 ;
}
public static void main (String[] args)
{
String s1 = "gfg" ;
String s2 = "gf" ;
if (isEditDistanceOne(s1, s2))
System.out.print( "Yes" );
else
System.out.print( "No" );
}
}
|
Python3
def isEditDistanceOne(s1, s2):
m = len (s1)
n = len (s2)
if abs (m - n) > 1 :
return false
count = 0
i = 0
j = 0
while i < m and j < n:
if s1[i] ! = s2[j]:
if count = = 1 :
return false
if m > n:
i + = 1
elif m < n:
j + = 1
else :
i + = 1
j + = 1
count + = 1
else :
i + = 1
j + = 1
if i < m or j < n:
count + = 1
return count = = 1
s1 = "gfg"
s2 = "gf"
if isEditDistanceOne(s1, s2):
print ( "Yes" )
else :
print ( "No" )
|
C#
using System;
class GFG
{
static bool isEditDistanceOne(String s1,
String s2)
{
int m = s1.Length, n = s2.Length;
if (Math.Abs(m - n) > 1)
return false ;
int count = 0;
int i = 0, j = 0;
while (i < m && j < n)
{
if (s1[i] != s2[j])
{
if (count == 1)
return false ;
if (m > n)
i++;
else if (m< n)
j++;
else
{
i++;
j++;
}
count++;
}
else
{
i++;
j++;
}
}
if (i < m || j < n)
count++;
return count == 1;
}
public static void Main ()
{
String s1 = "gfg" ;
String s2 = "gf" ;
if (isEditDistanceOne(s1, s2))
Console.WriteLine( "Yes" );
else
Console.WriteLine( "No" );
}
}
|
Javascript
<script>
function isEditDistanceOne(s1, s2)
{
let m = s1.length, n = s2.length;
if (Math.abs(m - n) > 1)
return false ;
let count = 0;
let i = 0, j = 0;
while (i < m && j < n)
{
if (s1[i] != s2[j])
{
if (count == 1)
return false ;
if (m > n)
i++;
else if (m< n)
j++;
else
{
i++;
j++;
}
count++;
}
else
{
i++;
j++;
}
}
if (i < m || j < n)
count++;
return count == 1;
}
let s1 = "gfg" ;
let s2 = "gf" ;
if (isEditDistanceOne(s1, s2))
document.write( "Yes" );
else
document.write( "No" );
</script>
|
PHP
<?php
function isEditDistanceOne( $s1 , $s2 )
{
$m = strlen ( $s1 );
$n = strlen ( $s2 );
if ( abs ( $m - $n ) > 1)
return false;
$count = 0;
$i = 0; $j = 0;
while ( $i < $m && $j < $n )
{
if ( $s1 [ $i ] != $s2 [ $j ])
{
if ( $count == 1)
return false;
if ( $m > $n )
$i ++;
else if ( $m < $n )
$j ++;
else
{
$i ++;
$j ++;
}
$count ++;
}
else
{
$i ++;
$j ++;
}
}
if ( $i < $m || $j < $n )
$count ++;
return $count == 1;
}
$s1 = "gfg" ;
$s2 = "gf" ;
if (isEditDistanceOne( $s1 , $s2 ))
echo "Yes" ;
else
echo "No" ;
?>
|
Time complexity: O(n)
Auxiliary Space: O(1)
Approach#2: Using dynamic programming
The approach of this code is to calculate the edit distance between two strings using dynamic programming and then check if it is equal to one or not. If the absolute difference in length of the strings is greater than one, it returns False without calculating the edit distance. Otherwise, it fills a 2D array with the minimum number of operations required to transform one string into another, using the operations of insertion, removal, and replacement. Finally, it returns True if the edit distance is equal to one, and False otherwise.
Algorithm
1. If the absolute difference between the lengths of s1 and s2 is greater than 1, return False.
2. Create a 2D array dp of size (n+1) x (m+1) where n is the length of s1 and m is the length of s2.
3. Initialize the first row and first column of dp with values from 0 to m and 0 to n respectively.
4. Traverse the dp array from (1,1) to (n,m) and check the following conditions:
If s1[i-1] and s2[j-1] are equal, set dp[i][j] to dp[i-1][j-1].
Otherwise, set dp[i][j] to 1 + min(dp[i][j-1], dp[i-1][j], dp[i-1][j-1]).
5. Return True if dp[n][m] is 1, else return False.
C++
#include <iostream>
#include <string>
using namespace std;
bool isEditDistanceOne(string s1, string s2) {
int n = s1.length();
int m = s2.length();
if ( abs (n - m) > 1)
return false ;
int dp[n + 1][m + 1];
for ( int i = 0; i <= n; i++) {
for ( int j = 0; j <= m; j++) {
if (i == 0)
dp[i][j] = j;
else if (j == 0)
dp[i][j] = i;
else 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],
min(dp[i - 1][j], dp[i - 1][j - 1]));
}
}
return dp[n][m] == 1;
}
int main() {
string s1 = "gfg" ;
string s2 = "gf" ;
cout << (isEditDistanceOne(s1, s2) ? "true" : "false" ) << endl;
return 0;
}
|
Java
public class EditDistanceOne {
public static boolean isEditDistanceOne(String s1, String s2) {
int n = s1.length();
int m = s2.length();
if (Math.abs(n - m) > 1 )
return false ;
int [][] dp = new int [n + 1 ][m + 1 ];
for ( int i = 0 ; i <= n; i++) {
for ( int j = 0 ; j <= m; j++) {
if (i == 0 )
dp[i][j] = j;
else if (j == 0 )
dp[i][j] = i;
else if (s1.charAt(i - 1 ) == s2.charAt(j - 1 ))
dp[i][j] = dp[i - 1 ][j - 1 ];
else
dp[i][j] = 1 + Math.min(dp[i][j - 1 ],
Math.min(dp[i - 1 ][j], dp[i - 1 ][j - 1 ]));
}
}
return dp[n][m] == 1 ;
}
public static void main(String[] args) {
String s1 = "gfg" ;
String s2 = "gf" ;
System.out.println(isEditDistanceOne(s1, s2));
}
}
|
Python3
def is_edit_distance_one(s1, s2):
n = len (s1)
m = len (s2)
if abs (n - m) > 1 :
return False
dp = [[ 0 for j in range (m + 1 )] for i in range (n + 1 )]
for i in range (n + 1 ):
for j in range (m + 1 ):
if i = = 0 :
dp[i][j] = j
elif j = = 0 :
dp[i][j] = i
elif 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[n][m] = = 1
s1 = "gfg"
s2 = "gf"
print (is_edit_distance_one(s1, s2))
|
C#
using System;
class GFG
{
static bool IsEditDistanceOne( string s1, string s2)
{
int n = s1.Length;
int m = s2.Length;
if (Math.Abs(n - m) > 1)
{
return false ;
}
int [,] dp = new int [n + 1, m + 1];
for ( int i = 0; i <= n; i++)
{
for ( int j = 0; j <= m; j++)
{
if (i == 0)
{
dp[i, j] = j;
}
else if (j == 0)
{
dp[i, j] = i;
}
else 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], Math.Min(dp[i - 1, j], dp[i - 1, j - 1]));
}
}
}
return dp[n, m] == 1;
}
static void Main()
{
string s1 = "gfg" ;
string s2 = "gf" ;
Console.WriteLine(IsEditDistanceOne(s1, s2) ? "true" : "false" );
}
}
|
Javascript
function is_edit_distance_one(s1, s2) {
let n = s1.length;
let m = s2.length;
if (Math.abs(n - m) > 1) {
return false ;
}
let dp = Array.from(Array(n + 1), () => new Array(m + 1).fill(0));
for (let i = 0; i <= n; i++) {
for (let j = 0; j <= m; j++) {
if (i == 0) {
dp[i][j] = j;
} else if (j == 0) {
dp[i][j] = i;
} else 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[n][m] == 1;
}
let s1 = "gfg" ;
let s2 = "gf" ;
console.log(is_edit_distance_one(s1, s2));
|
Time complexity: O(n^2)
Auxiliary Space: O(n^2)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...