Solution 1

Did not go through the solution yet!

Python · 2026-01-30
import math
class TrieNode:
    __slots__ = ("children", "id")
    def __init__(self):
        self.children = {}
        self.id = -1   # string id if this node is terminal

class Trie:
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, s: str, sid: int):
        node = self.root
        for ch in s:
            if ch not in node.children:
                node.children[ch] = TrieNode()
            node = node.children[ch]
        node.id = sid

class Solution:
    '''
    Did not go through the solution yet!
    '''
    def minimumCost(self, source: str, target: str,
                    original: List[str], changed: List[str], cost: List[int]) -> int:
        n = len(source)
        INF = 10**18

        # ---------- Step 1: assign ids ----------
        strings = {}
        sid = 0
        for s in original + changed:
            if s not in strings:
                strings[s] = sid
                sid += 1
        
        m = sid

        # ---------- Step 2: Floyd–Warshall ----------
        dist = [[INF] * m for _ in range(m)]
        for i in range(m):
            dist[i][i] = 0
        
        for o, c, w in zip(original, changed, cost):
            u, v = strings[o], strings[c]
            dist[u][v] = min(dist[u][v], w)
        
        for k in range(m):
            for i in range(m):
                if dist[i][k] == INF:
                    continue
                for j in range(m):
                    nd = dist[i][k] + dist[k][j]
                    if nd < dist[i][j]:
                        dist[i][j] = nd

        # ---------- Step 3: build tries ----------
        trieS = Trie()
        trieT = Trie()
        for s, i in strings.items():
            trieS.insert(s, i)
            trieT.insert(s, i)

        # ---------- Step 4: DP ----------
        dp = [INF] * (n + 1)
        dp[0] = 0

        for i in range(n):
            if dp[i] == INF:
                continue

            # Single character match
            if source[i] == target[i]:
                dp[i + 1] = min(dp[i + 1], dp[i])

            # Substring match via trie
            nodeS = trieS.root
            nodeT = trieT.root

            j = i
            while j < n:
                cs, ct = source[j], target[j]
                if cs not in nodeS.children or ct not in nodeT.children:
                    break
                nodeS = nodeS.children[cs]
                nodeT = nodeT.children[ct]

                if nodeS.id != -1 and nodeT.id != -1:
                    c = dist[nodeS.id][nodeT.id]
                    if c < INF:
                        dp[j + 1] = min(dp[j + 1], dp[i] + c)
                j += 1

        return -1 if dp[n] == INF else dp[n]
Leet Code/python.py · L4790–4884