단어 퍼즐은 주어진 단어 조각들을 이용해서 주어진 문장을 완성하는 퍼즐입니다. 이때, 주어진 각 단어 조각들은 각각 무한개씩 있다고 가정합니다. 예를 들어 주어진 단어 조각이 [“ba”, “na”, “n”, “a”]인 경우 ba, na, n, a 단어 조각이 각각 무한개씩 있습니다. 이때, 만들어야 하는 문장이 “banana”라면 “ba”, “na”, “n”, “a”의 4개를 사용하여 문장을 완성할 수 있지만, “ba”, “na”, “na”의 3개만을 사용해도 “banana”를 완성할 수 있습니다. 사용 가능한 단어 조각들을 담고 있는 배열 strs와 완성해야 하는 문자열 t가 매개변수로 주어질 때, 주어진 문장을 완성하기 위해 사용해야 하는 단어조각 개수의 최솟값을 return 하도록 solution 함수를 완성해 주세요. 만약 주어진 문장을 완성하는 것이 불가능하면 -1을 return 하세요.
제한사항
이 문제는 DP를 사용한 풀이법과 BFS를 이용한 풀이법이 있다.
class Solution {
public int solution(String[] strs, String t) {
int answer = Integer.MAX_VALUE;
int[] dp = new int[t.length()];
for (int i = 1; i < t.length() + 1; i++) {
for (int j = 0; j < strs.length; j++) {
String puzzle = strs[j];
if (i - puzzle.length() < 0) continue;
if (puzzle.equals(t.substring(i - puzzle.length(), i))) {
if (i - puzzle.length() == 0) {
dp[i - 1] = 1;
continue;
}
if (dp[i - puzzle.length() - 1] > 0) {
dp[i - 1] = dp[i - 1] == 0 ? dp[i - puzzle.length() - 1] + 1:
Math.min(dp[i - 1], dp[i - puzzle.length() - 1] + 1);
}
}
}
}
answer = dp[dp.length - 1];
if (answer == 0) return -1;
return answer;
}
}
class Solution {
public int solution(String[] strs, String t) {
int answer = 0;
Graph graph = new Graph();
for (int i = 0; i < strs.length; i++) {
String thisStr = strs[i];
int a = 0;
int count = 0;
while (a != -1){
int add = 0;
if (count > 0) {
add = 1;
}
int start = t.indexOf(thisStr, a + add);
int end = start + thisStr.length();
if (start != -1) {
if (graph.containsNode(start)) {
Node node = graph.getNode(start);
node.addEdge(end);
}
else {
Node node = new Node(start);
node.addEdge(end);
graph.addNode(node);
}
}
a = start;
count ++;
}
}
return graph.shortestPath(t.length(), t.length());
}
}
class Graph{
public HashMap<Integer, Node> nodeMap = new HashMap<Integer, Node>();
public Graph() {
nodeMap = new HashMap<Integer, Node>();
}
public void addNode(Node node) {
nodeMap.put(node.source, node);
}
public boolean containsNode(int source) {
return nodeMap.containsKey(source);
}
public Node getNode(int index) {
return nodeMap.get(index);
}
public int shortestPath(int end, int strLeng) {
Queue<int[]> queue = new LinkedList<>();
boolean visited[] = new boolean[strLeng];
queue.add(new int[]{0, 0});
visited[0] = true;
while (queue.size() > 0) {
int[] currentNode = queue.poll();
if (nodeMap.containsKey(currentNode[0])){
ArrayList<Integer> destArr = nodeMap.get(currentNode[0]).destArr;
for (int i = 0; i < destArr.size(); i++) {
if (destArr.get(i) == end) {
return currentNode[1] + 1;
}
if (!visited[destArr.get(i)]){
visited[destArr.get(i)] = true;
queue.add(new int[]{destArr.get(i), currentNode[1] + 1});
}
}
}
}
return -1;
}
}
class Node {
public int source;
public ArrayList<Integer> destArr;
public Node(int source) {
this.source = source;
this.destArr = new ArrayList<Integer> ();
}
public void addEdge(int end) {
destArr.add(end);
}
}
속도는 BFS가 조금더 빠르지만 둘다 효율성 테스트는 통과한다.