124 字符串的转换路径问题
Table of Contents

ac

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;


public class Main {
    public static Scanner sc = new Scanner(System.in);

    public static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

    static int size = 3;

    public static void main(String[] args) throws Exception {
        String nStr = reader.readLine();
        int n = Integer.valueOf(nStr);
        String s12 = reader.readLine();
        String[] sArr = s12.split(" ");
        String[] strs = new String[n];
        for(int i=0;i<n;i++){
            strs[i] = reader.readLine();
        }
        String s1 = sArr[0];
        String s2 = sArr[1];

        // 映射地图 next 构造
        Map<String, List<String>> mp = new HashMap<>();
        for(int i=0;i<n;i++){
            List<String> sonList = new ArrayList<>();
            for(int j=0;j<n;j++){
                if(j == i){
                    continue;
                }
                if(isChangeOne(strs[i], strs[j])){
                    sonList.add(strs[j]);
                }
            }
            Collections.sort(sonList);
            mp.put(strs[i], sonList);
        }
        // 处理 s1 的 next
        List<String> sonList = new ArrayList<>();
        for(int i=0;i<n;i++){
            if(isChangeOne(s1, strs[i])){
                sonList.add(strs[i]);
            }
            Collections.sort(sonList);
            mp.put(s1, sonList);
        }

        Map<String, Integer> mpCeng = new HashMap<>();
        Set<String> vis = new HashSet<>();
        Queue<String> que = new LinkedList<>();
        Queue<Integer> queCeng = new LinkedList<>();
        que.offer(s1);
        queCeng.offer(0);
        vis.add(s1);
        while (!que.isEmpty()){
            String str = que.poll();
            int ceng = queCeng.poll();
            mpCeng.put(str, ceng);
            if(!mp.get(str).isEmpty()){
                for(String sNext: mp.get(str)){
                    if(!vis.contains(sNext)) {
                        que.offer(sNext);
                        queCeng.offer(ceng + 1);
                        vis.add(sNext);
                    }
                }
            }
        }
        List<String> onePath = new ArrayList<>();
        onePath.add(s1);
        dfs(s1, s2, mp, mpCeng, onePath);
        if(ans.isEmpty()){
            System.out.println("NO");
        }else {
            System.out.println("YES");
            for(int i=0;i<ans.size();i++){
                System.out.println(ans.get(i));
            }
        }
    }

    static int minLen = Integer.MAX_VALUE;
    static List<String> ans = new ArrayList<>();

    // 将结果直接转成要打印的字符串
    static String printOnePath(List<String> onePath, int len){
        StringBuffer sb = new StringBuffer();
        for(int i=0;i<len-1;i++){
           sb.append(onePath.get(i) + " -> ");
        }
        sb.append(onePath.get(len-1));
        return sb.toString();
    }

    static void dfs(String cur, String s2,
             Map<String, List<String>> mp,
             Map<String, Integer> mpCeng,
             List<String> onePath)
    {
        if(onePath.size() > minLen){
            return;
        }
        if(cur.equals(s2)){
            int len = onePath.size();
            if(len < minLen){
                ans.clear();
                ans.add(printOnePath(onePath, len));
                minLen = len;
            }else if(len == minLen){
                ans.add(printOnePath(onePath, len));
            }
            return;
        }
        List<String> sonList = mp.get(cur);
        for(String nextStr: sonList){
            if(mpCeng.get(nextStr) == mpCeng.get(cur) + 1){
                onePath.add(nextStr);
                dfs(nextStr, s2, mp, mpCeng, onePath);
                onePath.remove(nextStr);
            }
        }
    }

    // 是否改变一个字符就能从 src 到 des
    static boolean isChangeOne(String src, String des){
        if(src == null || des == null || src.length() != size || des.length() != size){
            return false;
        }
        int changeSize = 0;
        for(int i=0;i<size;i++){
            if(src.charAt(i) != des.charAt(i)){
                changeSize ++;
            }
        }
        if(changeSize == 1){
            return true;
        }
        return false;
    }
}
/*
8
abc cab
cab
acc
cbc
ccc
cac
cbb
aab
abb

YES
abc -> abb -> aab -> cab
abc -> abb -> cbb -> cab
abc -> cbc -> cac -> cab
abc -> cbc -> cbb -> cab
*/