POJ-3803, AOJ-1296: Repeated Substitution with Sed
keyword
反復深化 Java
問題概要
あるルールα→βというルールがN(<10)個ある。このルールとは、JavaでいうところのreplaceAll(α、β)という作用である。文字γをδにするのに必要な最小回数を求める問題。できなければ-1を出力する。1<=|α|<=|β|<=10, 1<=|γ|<=|δ|<=10。
解法
何か数字がやたら小さいし探索臭がするので反復深化で書いた。多分BFSでも通る。文字列の長さで枝刈りを入れた。上限はよくわかってないけど10*10=100回だと大丈夫だった。実装時間は45分くらい( for(int maxDepth=1; maxDepth<=100; maxDepth++) と書いていたのにずっと気づかなかった)。
import java.util.HashMap; import java.util.HashSet; import java.util.Scanner; import java.util.Set; public class Main{ int maxDepth; String goal, cur; HashMap<String, String> dict; String[] rule; int N; Set<String> visited; void run(){ Scanner in = new Scanner(System.in); for(;;){ N = in.nextInt(); if(N==0) return ; dict = new HashMap<String, String>(); rule = new String[N]; for(int i=0; i<N; i++){ rule[i] = in.next(); dict.put(rule[i], in.next()); } cur = in.next(); goal = in.next(); System.out.println(solve()); } } int solve(){ if(cur.equals(goal)) return 0; for(maxDepth = 1; maxDepth <= 100; maxDepth++){ visited = new HashSet<String>(); if(dfs(0)) return maxDepth; } return -1; } boolean dfs(int depth){ if(depth > maxDepth || cur.length() > goal.length() || visited.contains(cur)) return false; if(depth > maxDepth) return false; if(cur.equals(goal)) return true; visited.add(cur); String tmp = cur.toString(); for(int i=0; i<N; i++){ cur = tmp.replaceAll(rule[i], dict.get(rule[i])); if(dfs(depth+1)) return true; } cur = tmp.toString(); return false; } public static void main(String args[]){ new Main().run(); } }