Hard
You are given two strings, word1
and word2
, of equal length. You need to transform word1
into word2
.
For this, divide word1
into one or more contiguous **substring**. For each substring substr
you can perform the following operations:
Replace: Replace the character at any one index of substr
with another lowercase English letter.
Swap: Swap any two characters in substr
.
Reverse Substring: Reverse substr
.
Each of these counts as one operation and each character of each substring can be used in each type of operation at most once (i.e. no single index may be involved in more than one replace, one swap, or one reverse).
Return the minimum number of operations required to transform word1
into word2
.
Example 1:
Input: word1 = “abcdf”, word2 = “dacbe”
Output: 4
Explanation:
Divide word1
into "ab"
, "c"
, and "df"
. The operations are:
"ab"
,
"ab" -> "ba"
."ba" -> "da"
."c"
do no operations."df"
,
"df" -> "bf"
."bf" -> "be"
.Example 2:
Input: word1 = “abceded”, word2 = “baecfef”
Output: 4
Explanation:
Divide word1
into "ab"
, "ce"
, and "ded"
. The operations are:
"ab"
,
"ab" -> "ba"
."ce"
,
"ce" -> "ec"
."ded"
,
"ded" -> "fed"
."fed" -> "fef"
.Example 3:
Input: word1 = “abcdef”, word2 = “fedabc”
Output: 2
Explanation:
Divide word1
into "abcdef"
. The operations are:
"abcdef"
,
"abcdef" -> "fedcba"
."fedcba" -> "fedabc"
.Constraints:
1 <= word1.length == word2.length <= 100
word1
and word2
consist only of lowercase English letters.import kotlin.math.min
class Solution {
fun minOperations(word1: String, word2: String): Int {
val dp = IntArray(word1.length)
val count: Array<IntArray> = Array<IntArray>(26) { IntArray(26) }
for (i in 0..<word1.length) {
dp[i] = Int.Companion.MAX_VALUE
}
for (i in 0..<word1.length) {
for (j in i downTo 0) {
var c1 = 0
var c2 = 0
run {
var k1 = j
var k2 = j
while (k1 <= i && k2 <= i) {
val ints = count[word2[k2].code - 'a'.code]
if (ints[word1[k1].code - 'a'.code] > 0) {
ints[word1[k1].code - 'a'.code]--
} else if (word1[k1] != word2[k2]) {
count[word1[k1].code - 'a'.code][word2[k2].code - 'a'.code]++
c1++
}
k1++
k2++
}
}
run {
var k1 = j
var k2 = j
while (k1 <= i && k2 <= i) {
count[word1[k1].code - 'a'.code][word2[k2].code - 'a'.code] = 0
k1++
k2++
}
}
dp[i] = min(dp[i], if (j - 1 < 0) c1 else dp[j - 1] + c1)
run {
var k1 = j
var k2 = i
while (k1 <= i && k2 >= j) {
val ints = count[word2[k2].code - 'a'.code]
if (ints[word1[k1].code - 'a'.code] > 0) {
ints[word1[k1].code - 'a'.code]--
} else if (word1[k1].code - 'a'.code != word2[k2].code - 'a'.code) {
count[word1[k1].code - 'a'.code][word2[k2].code - 'a'.code]++
c2++
}
k1++
k2--
}
}
var k1 = j
var k2 = i
while (k1 <= i && k2 >= j) {
count[word1[k1].code - 'a'.code][word2[k2].code - 'a'.code] = 0
k1++
k2--
}
dp[i] = min(dp[i], if (j - 1 < 0) c2 + 1 else dp[j - 1] + c2 + 1)
}
}
return dp[word1.length - 1]
}
}