From b43603c1763cdb2ca313fd6f739f64ddd318b97e Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sat, 13 Jul 2024 07:43:48 +0300 Subject: [PATCH 1/5] Improved task 3213 --- .../Solution.java | 169 ++++++++++++++---- 1 file changed, 130 insertions(+), 39 deletions(-) diff --git a/src/main/java/g3201_3300/s3213_construct_string_with_minimum_cost/Solution.java b/src/main/java/g3201_3300/s3213_construct_string_with_minimum_cost/Solution.java index 033d705ca..4fbbeecff 100644 --- a/src/main/java/g3201_3300/s3213_construct_string_with_minimum_cost/Solution.java +++ b/src/main/java/g3201_3300/s3213_construct_string_with_minimum_cost/Solution.java @@ -1,62 +1,153 @@ package g3201_3300.s3213_construct_string_with_minimum_cost; // #Hard #Array #String #Dynamic_Programming #Suffix_Array -// #2024_07_09_Time_182_ms_(100.00%)_Space_61.4_MB_(72.97%) +// #2024_07_13_Time_1907_ms_(5.01%)_Space_100.9_MB_(5.09%) +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class Solution { - private static int invalid = Integer.MAX_VALUE; - - private static class Node { - int cost = -1; - Node[] chd = new Node[26]; + List buildKmpPrefix(String target) { + List w = new ArrayList<>(Collections.nCopies(target.length(), 0)); + int k = 0; + int i = 1; + while (i < target.length()) { + if (target.charAt(i) == target.charAt(k)) { + k++; + w.set(i, k); + i++; + } else { + if (k != 0) { + k = w.get(k - 1); + } else { + i++; + } + } + } + return w; } - private Node rt; + List> find(List prefix, String target, String w) { + List> result = new ArrayList<>(); + int m = target.length(); + int n = w.length(); + int i = 0; + int k = 0; + while (i < m) { + if (target.charAt(i) == w.charAt(k)) { + i++; + k++; + } + if (k == n) { + result.add(Arrays.asList(i - k, i)); + k = prefix.get(k - 1); + } else if (i < m && target.charAt(i) != w.charAt(k)) { + if (k != 0) { + k = prefix.get(k - 1); + } else { + i++; + } + } + } + return result; + } public int minimumCost(String target, String[] words, int[] costs) { - rt = new Node(); - int m = words.length; - int n = target.length(); - for (int i = 0; i < m; ++i) { - if (words[i].length() <= n) { - insert(words[i], costs[i]); + List targetPrefix = buildKmpPrefix(target); + Node root = new Node(); + for (int j = 0; j < words.length; j++) { + String x = words[j]; + if (x.length() < 320) { + Node p = root; + for (int i = 0; i < x.length(); i++) { + char c = x.charAt(i); + p.children.putIfAbsent(c, new Node()); + p = p.children.get(c); + if (i == x.length() - 1) { + if (p.cost == null) { + p.cost = costs[j]; + } else { + p.cost = Math.min(costs[j], p.cost); + } + } + } + } + } + Map> dm = new HashMap<>(); + for (int i = 0; i < words.length; i++) { + String word = words[i]; + if (word.length() >= 320) { + List> q = find(targetPrefix, target, word); + for (List pair : q) { + int b = pair.get(0); + int e = pair.get(1); + dm.putIfAbsent(e, new HashMap<>()); + Map qm = dm.get(e); + qm.put(b, qm.getOrDefault(b, Integer.MAX_VALUE)); + qm.put(b, Math.min(qm.get(b), costs[i])); + } } } - int[] dp = new int[n + 1]; - Arrays.fill(dp, invalid); + List d = new ArrayList<>(); + d.add(new NodeCostPair(root, 0)); + int[] dp = new int[target.length() + 1]; + Arrays.fill(dp, -1); dp[0] = 0; - for (int i = 0; i < n; ++i) { - if (dp[i] == invalid) { - continue; - } - int nowC = dp[i]; - Node now = rt; - for (int j = i; now != null && j < n; ++j) { - int ch = target.charAt(j) - 'a'; - now = now.chd[ch]; - if (now != null && now.cost != -1) { - dp[j + 1] = Math.min(dp[j + 1], nowC + now.cost); + for (int i = 0; i < target.length(); i++) { + char x = target.charAt(i); + List q = new ArrayList<>(); + Integer t = null; + for (NodeCostPair pair : d) { + Node p = pair.node; + int cost = pair.cost; + if (p.children.containsKey(x)) { + Node w = p.children.get(x); + if (w.cost != null) { + t = t == null ? cost + w.cost : Math.min(t, cost + w.cost); + } + q.add(new NodeCostPair(w, cost)); + } + } + Map qm = dm.getOrDefault(i + 1, Collections.emptyMap()); + for (Map.Entry entry : qm.entrySet()) { + int b = entry.getKey(); + if (dp[b] >= 0) { + t = + t == null + ? dp[b] + entry.getValue() + : Math.min(t, dp[b] + entry.getValue()); } } + if (t != null) { + dp[i + 1] = t; + q.add(new NodeCostPair(root, t)); + } + d = q; } - - return dp[n] == invalid ? -1 : dp[n]; + return dp[target.length()]; } - private void insert(String wd, int cst) { - int len = wd.length(); - Node now = rt; - for (int i = 0; i < len; ++i) { - int ch = wd.charAt(i) - 'a'; - if (now.chd[ch] == null) { - now.chd[ch] = new Node(); - } - now = now.chd[ch]; + private static class Node { + Map children; + Integer cost; + + public Node() { + this.children = new HashMap<>(); + this.cost = null; } - if (now.cost == -1 || now.cost > cst) { - now.cost = cst; + } + + private static class NodeCostPair { + Node node; + int cost; + + public NodeCostPair(Node node, int cost) { + this.node = node; + this.cost = cost; } } } From 0719b925f7ea9d4e7480096a2012561853fc3ba3 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sat, 13 Jul 2024 14:56:00 +0300 Subject: [PATCH 2/5] Update Solution.java --- .../s3213_construct_string_with_minimum_cost/Solution.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/g3201_3300/s3213_construct_string_with_minimum_cost/Solution.java b/src/main/java/g3201_3300/s3213_construct_string_with_minimum_cost/Solution.java index 4fbbeecff..8849522e3 100644 --- a/src/main/java/g3201_3300/s3213_construct_string_with_minimum_cost/Solution.java +++ b/src/main/java/g3201_3300/s3213_construct_string_with_minimum_cost/Solution.java @@ -87,8 +87,8 @@ public int minimumCost(String target, String[] words, int[] costs) { int e = pair.get(1); dm.putIfAbsent(e, new HashMap<>()); Map qm = dm.get(e); - qm.put(b, qm.getOrDefault(b, Integer.MAX_VALUE)); - qm.put(b, Math.min(qm.get(b), costs[i])); + int value = qm.getOrDefault(b, Integer.MAX_VALUE)); + qm.put(b, Math.min(value, costs[i])); } } } From 91984241bb05911a32643bf4e7f24ea75c4cde38 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sat, 13 Jul 2024 21:43:58 +0300 Subject: [PATCH 3/5] Update Solution.java --- .../s3213_construct_string_with_minimum_cost/Solution.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/g3201_3300/s3213_construct_string_with_minimum_cost/Solution.java b/src/main/java/g3201_3300/s3213_construct_string_with_minimum_cost/Solution.java index 8849522e3..4fbbeecff 100644 --- a/src/main/java/g3201_3300/s3213_construct_string_with_minimum_cost/Solution.java +++ b/src/main/java/g3201_3300/s3213_construct_string_with_minimum_cost/Solution.java @@ -87,8 +87,8 @@ public int minimumCost(String target, String[] words, int[] costs) { int e = pair.get(1); dm.putIfAbsent(e, new HashMap<>()); Map qm = dm.get(e); - int value = qm.getOrDefault(b, Integer.MAX_VALUE)); - qm.put(b, Math.min(value, costs[i])); + qm.put(b, qm.getOrDefault(b, Integer.MAX_VALUE)); + qm.put(b, Math.min(qm.get(b), costs[i])); } } } From 7c5f710f801c40264a22455e81163f02955ddf07 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sun, 14 Jul 2024 06:38:29 +0300 Subject: [PATCH 4/5] Fixed sonar --- .../s3213_construct_string_with_minimum_cost/Solution.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/g3201_3300/s3213_construct_string_with_minimum_cost/Solution.java b/src/main/java/g3201_3300/s3213_construct_string_with_minimum_cost/Solution.java index 4fbbeecff..c7e3b4d72 100644 --- a/src/main/java/g3201_3300/s3213_construct_string_with_minimum_cost/Solution.java +++ b/src/main/java/g3201_3300/s3213_construct_string_with_minimum_cost/Solution.java @@ -87,8 +87,11 @@ public int minimumCost(String target, String[] words, int[] costs) { int e = pair.get(1); dm.putIfAbsent(e, new HashMap<>()); Map qm = dm.get(e); - qm.put(b, qm.getOrDefault(b, Integer.MAX_VALUE)); - qm.put(b, Math.min(qm.get(b), costs[i])); + if (qm.containsKey(b)) { + qm.put(b, Math.min(qm.get(b), costs[i])); + } else { + qm.put(b, costs[i]); + } } } } From 00c04b1aa51c55bd68415b16be8384ea63931443 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sun, 14 Jul 2024 06:55:38 +0300 Subject: [PATCH 5/5] Fixed sonar --- .../Solution.java | 65 +++++++++++-------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/src/main/java/g3201_3300/s3213_construct_string_with_minimum_cost/Solution.java b/src/main/java/g3201_3300/s3213_construct_string_with_minimum_cost/Solution.java index c7e3b4d72..0ca71417a 100644 --- a/src/main/java/g3201_3300/s3213_construct_string_with_minimum_cost/Solution.java +++ b/src/main/java/g3201_3300/s3213_construct_string_with_minimum_cost/Solution.java @@ -77,24 +77,8 @@ public int minimumCost(String target, String[] words, int[] costs) { } } } - Map> dm = new HashMap<>(); - for (int i = 0; i < words.length; i++) { - String word = words[i]; - if (word.length() >= 320) { - List> q = find(targetPrefix, target, word); - for (List pair : q) { - int b = pair.get(0); - int e = pair.get(1); - dm.putIfAbsent(e, new HashMap<>()); - Map qm = dm.get(e); - if (qm.containsKey(b)) { - qm.put(b, Math.min(qm.get(b), costs[i])); - } else { - qm.put(b, costs[i]); - } - } - } - } + Map> dm = + getIntegerMapMap(target, words, costs, targetPrefix); List d = new ArrayList<>(); d.add(new NodeCostPair(root, 0)); int[] dp = new int[target.length() + 1]; @@ -115,16 +99,7 @@ public int minimumCost(String target, String[] words, int[] costs) { q.add(new NodeCostPair(w, cost)); } } - Map qm = dm.getOrDefault(i + 1, Collections.emptyMap()); - for (Map.Entry entry : qm.entrySet()) { - int b = entry.getKey(); - if (dp[b] >= 0) { - t = - t == null - ? dp[b] + entry.getValue() - : Math.min(t, dp[b] + entry.getValue()); - } - } + t = getInteger(dm, i, dp, t); if (t != null) { dp[i + 1] = t; q.add(new NodeCostPair(root, t)); @@ -134,6 +109,40 @@ public int minimumCost(String target, String[] words, int[] costs) { return dp[target.length()]; } + private Integer getInteger(Map> dm, int i, int[] dp, Integer t) { + Map qm = dm.getOrDefault(i + 1, Collections.emptyMap()); + for (Map.Entry entry : qm.entrySet()) { + int b = entry.getKey(); + if (dp[b] >= 0) { + t = t == null ? dp[b] + entry.getValue() : Math.min(t, dp[b] + entry.getValue()); + } + } + return t; + } + + private Map> getIntegerMapMap( + String target, String[] words, int[] costs, List targetPrefix) { + Map> dm = new HashMap<>(); + for (int i = 0; i < words.length; i++) { + String word = words[i]; + if (word.length() >= 320) { + List> q = find(targetPrefix, target, word); + for (List pair : q) { + int b = pair.get(0); + int e = pair.get(1); + dm.putIfAbsent(e, new HashMap<>()); + Map qm = dm.get(e); + if (qm.containsKey(b)) { + qm.put(b, Math.min(qm.get(b), costs[i])); + } else { + qm.put(b, costs[i]); + } + } + } + } + return dm; + } + private static class Node { Map children; Integer cost;