题目地址:
https://www.lintcode.com/problem/parser/description
给定一个字符,再给定一个映射规则,可以把某个字符映射成一个字符串。问从这个字符出发是否可以经过若干次映射使之变为给定的另一个字符串。
思路是图的遍历,可以用DFS来做。首先需要建立图模型,可以将字符串都想象为图上的顶点,如果从某字符串经过映射规则可以变为另一个字符串,那么就有一条有向边。接下来只需要套用DFS的模板就可以了。代码如下:
import java.util.*;
public class Solution {
/**
* @param generator: Generating set of rules.
* @param startSymbol: Start symbol.
* @param symbolString: Symbol string.
* @return: Return true if the symbol string can be generated, otherwise return false.
*/
public boolean canBeGenerated(String[] generator, char startSymbol, String symbolString) {
// Write your code here.
// 将映射关系储存进一个map中
Map<Character, Set<String>> map = new HashMap<>();
for (String s : generator) {
String[] split = s.split(" -> ");
map.putIfAbsent(split[0].charAt(0), new HashSet<>());
map.get(split[0].charAt(0)).add(split[1]);
}
return dfs(String.valueOf(startSymbol), symbolString, map);
}
// 从start开始做DFS
private boolean dfs(String start, String symbol, Map<Character, Set<String>> map) {
// 如果start等于了symbol,说明存在路径,返回true
if (start.equals(symbol)) {
return true;
}
// 如果start的长度长于symbol,那不可能还能变成symbol了,返回false
if (start.length() > symbol.length()) {
return false;
}
// 生成start的邻居节点,并进行DFS
for (String neighbor : getNeighbors(start, map)) {
if (dfs(neighbor, symbol, map)) {
return true;
}
}
return false;
}
private List<String> getNeighbors(String s, Map<Character, Set<String>> map) {
List<String> neighbors = new ArrayList<>();
for (int i = 0; i < s.length(); i++) {
Set<String> replacement = map.get(s.charAt(i));
if (replacement != null) {
for (String replace : replacement) {
neighbors.add(s.substring(0, i) + replace + s.substring(i + 1));
}
}
}
return neighbors;
}
}
时空复杂度 。