Celestial Pattern Synthesis
In Celestial Pattern Synthesis you must build a target mural string using available snippets each with a cost Snippets may be reused and may overlap as long as every placed character matches the mural exactly The primary objective is minimum total cost If multiple constructions share that minimum cost you must return the lexicographically smallest sequence of snippet indices according to the required build order A practical model is shortest path DP over mural positions State i means prefix length i already built A transition exists when a snippet matches starting at i moving to i len snippet with added cost Besides cost track reconstruction metadata for index-sequence tie-breaking For equal-cost alternatives compare candidate sequences lexicographically and keep the smaller one If position N is unreachable return cost 1 with an empty sequence The judge checks tie situations impossible builds and repeated snippet use Correctness depends on both numeric optimality and exact sequence ordering not just feasibility Keep transitions strict on character matching and maintain deterministic tie resolution This hard challenge combines string matching graph-style DP and stable lexicographic decision logic in one optimization pipeline In practice this means storing both best cost and a comparable representation of the chosen index sequence for each position state Tie-breaking cannot be an afterthought if sequence order is not enforced during transitions you can get correct cost but wrong official output ordering When the task involves connectivity or route cost build adjacency carefully
Examples
Example 1: Minimal cost solution using snippets at indices 2 and 3
Example 2: Using snippet at index 2 four times
Example 3: No valid solution exists
Algorithm Flow

Best Answers
import java.util.*;
class Solution {
public Object[] celestial_pattern_synthesis(String mural, List<Object[]> snippets) {
if (mural == null || mural.isEmpty()) return new Object[]{0L, new ArrayList<Integer>()};
int N = mural.length();
int M = snippets.size();
List<Occ>[] occurrences = new List[M];
for (int i = 0; i < M; i++) {
occurrences[i] = new ArrayList<>();
String pat = (String) snippets.get(i)[0];
int start = 0;
while ((start = mural.indexOf(pat, start)) != -1) {
occurrences[i].add(new Occ(start, start + pat.length()));
start++;
}
}
long[] dp = new long[N + 1];
Arrays.fill(dp, Long.MAX_VALUE);
dp[N] = 0;
List<Match>[] byEnd = new List[N + 1];
for (int i = 0; i <= N; i++) byEnd[i] = new ArrayList<>();
for (int i = 0; i < M; i++) {
int cost = ((Number) snippets.get(i)[1]).intValue();
for (Occ occ : occurrences[i]) byEnd[occ.end].add(new Match(occ.start, cost));
}
PriorityQueue<PQItem> pq = new PriorityQueue<>((a, b) -> Long.compare(a.val, b.val));
for (int i = N; i > 0; i--) {
if (dp[i] != Long.MAX_VALUE) {
for (Match m : byEnd[i]) pq.add(new PQItem(m.cost + dp[i], m.start));
}
while (!pq.isEmpty() && pq.peek().start > i - 1) pq.poll();
if (!pq.isEmpty()) dp[i - 1] = pq.peek().val;
}
if (dp[0] == Long.MAX_VALUE) return new Object[]{-1L, new ArrayList<Integer>()};
List<Integer> resSeq = new ArrayList<>();
int curr = 0;
while (curr < N) {
int bestIdx = Integer.MAX_VALUE;
int bestEnd = -1;
for (int j = 0; j < M; j++) {
int cost = ((Number) snippets.get(j)[1]).intValue();
int idx = j + 1;
if (idx > bestIdx) continue;
for (Occ occ : occurrences[j]) {
if (occ.start <= curr && occ.end > curr) {
if (dp[occ.end] != Long.MAX_VALUE && cost + dp[occ.end] == dp[curr]) {
if (idx < bestIdx) {
bestIdx = idx;
bestEnd = occ.end;
} else {
bestEnd = Math.max(bestEnd, occ.end);
}
break;
}
}
}
}
resSeq.add(bestIdx);
curr = bestEnd;
}
return new Object[]{dp[0], resSeq};
}
static class Occ { int start, end; Occ(int s, int e) { start = s; end = e; } }
static class Match { int start, cost; Match(int s, int c) { start = s; cost = c; } }
static class PQItem { long val; int start; PQItem(long v, int s) { val = v; start = s; } }
}Comments (0)
Join the Discussion
Share your thoughts, ask questions, or help others with this problem.
