输入包括两行,第一行一个字符串,代表str1,第二行一个字符串,代表str2。
如果str2是str1的旋变字符串请输出“YES”,否则输出“NO”。
abcd dbac
YES
abcd->d...abc->d...ab...c->d...b...a...c
IJz JzI
YES
左边为l右边为Jz交换 变Jzl
时间复杂度,额外空间复杂度。
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; import java.util.HashMap; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); char[] str1 = br.readLine().toCharArray(); char[] str2 = br.readLine().toCharArray(); int n = str1.length; if(!isSameAlpha(str1, str2)){ // 检查一下两个字符串是否有相同的字符 System.out.println("No"); }else{ System.out.println(recurrent(str1, str2, 0, 0, n)? "YES": "NO"); } } private static boolean recurrent(char[] str1, char[] str2, int L1, int L2, int size) { // base case字符串长度为1的时候直接判断两个串是否相等就行 if(size == 1){ return str1[L1] == str2[L2]; } for(int leftPart = 1; leftPart < size; leftPart++){ // 尝试左边字符的数量 if((recurrent(str1, str2, L1, L2, leftPart) && recurrent(str1, str2, L1 + leftPart, L2 + leftPart, size - leftPart)) || (recurrent(str1, str2, L1, L2 + size - leftPart, leftPart) && recurrent(str1, str2, L1 + leftPart, L2, size - leftPart))){ return true; } } return false; } private static boolean isSameAlpha(char[] str1, char[] str2) { if(str1.length != str2.length) return false; HashMap<Character, Integer> map1 = new HashMap<>(), map2 = new HashMap<>(); for(int i = 0; i < str1.length; i++){ map1.put(str1[i], map1.getOrDefault(str1[i], 0) + 1); map2.put(str2[i], map2.getOrDefault(str2[i], 0) + 1); } for(char c: map1.keySet()){ if(!map2.containsKey(c) || map1.get(c) != map2.get(c)) return false; } return true; } }写出递归版本后,改成动态规划的思路就更加清晰,不容易出错
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; import java.util.HashMap; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); char[] str1 = br.readLine().toCharArray(); char[] str2 = br.readLine().toCharArray(); int n = str1.length; if(!isSameAlpha(str1, str2)){ // 检查一下两个字符串是否有相同的字符 System.out.println("NO"); }else{ System.out.println(dynamicProgramming(str1, str2)? "YES": "NO"); } } private static boolean dynamicProgramming(char[] str1, char[] str2) { int n = str1.length; boolean[][][] dp = new boolean[n][n][n + 1]; // base case考虑的串长度为1时,只要字符相等就是旋变串 for(int l1 = 0; l1 < n; l1++){ for(int l2 = 0; l2 < n; l2++){ dp[l1][l2][1] = str1[l1] == str2[l2]; } } for(int size = 2; size <= n; size++){ for(int l1 = 0; l1 <= n - size; l1++){ for(int l2 = 0; l2 <= n - size; l2++){ for(int leftPart = 1; leftPart < size; leftPart++){ if((dp[l1][l2][leftPart] && dp[l1 + leftPart][l2 + leftPart][size - leftPart]) || (dp[l1][l2 + size - leftPart][leftPart] && dp[l1 + leftPart][l2][size - leftPart])){ dp[l1][l2][size] = true; // 只要有一个leftPart满足旋变串条件就可以break出去 break; } } } } } return dp[0][0][n]; } private static boolean isSameAlpha(char[] str1, char[] str2) { if(str1.length != str2.length) return false; HashMap<Character, Integer> map1 = new HashMap<>(), map2 = new HashMap<>(); for(int i = 0; i < str1.length; i++){ map1.put(str1[i], map1.getOrDefault(str1[i], 0) + 1); map2.put(str2[i], map2.getOrDefault(str2[i], 0) + 1); } for(char c: map1.keySet()){ if(!map2.containsKey(c) || map1.get(c) != map2.get(c)) return false; } return true; } }