输入包括两行,第一行一个字符串,代表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; } }
#include <stdio.h> #include <stdbool.h> #include <string.h> #define MAXLEN 101 bool is_valid(char *str1, char *str2) { int char_map[256]; memset(char_map, 0, sizeof(int) * 256); for (int i = 0; i < strlen(str1); i++) { char_map[str1[i]]++; } for (int i = 0; i < strlen(str2); i++) { if (--char_map[str2[i]] < 0) { return false; } } return true; } bool dp[MAXLEN][MAXLEN][MAXLEN]; int main(void) { char str1[MAXLEN], str2[MAXLEN]; scanf("%s%s", str1, str2); if (!is_valid(str1, str2)) { printf("%s\n", "NO"); return 0; } int len1 = (int) strlen(str1); int len2 = (int) strlen(str2); for (int i = 0; i < len1; i++) { for (int j = 0; j < len2; j++) { dp[i][j][1] = str1[i] == str2[j]; } } for (int s = 2; s <= len1; s++) { for (int i = 0; i < len1; i++) { for (int j = 0; j < len2; j++) { for (int ls = 1; ls < s; ls++) { if ((dp[i][j][ls] && dp[i + ls][j + ls][s - ls]) || (dp[i][j + s - ls][ls] && dp[i + ls][j][s - ls])) { dp[i][j][s] = true; break; } } } } } printf("%s\n", dp[0][0][len1] ? "YES" : "NO"); return 0; }
Rust
fn is_scramble(s1: String, s2: String) -> bool { if s1 == s2 { return true; } let s1 = s1.trim().chars().collect::<Vec<_>>(); let s2 = s2.trim().chars().collect::<Vec<_>>(); let mut s3 = s1.clone(); let mut s4 = s2.clone(); s3.sort_unstable(); s4.sort_unstable(); if s3 != s4 { return false; } let n = s1.len(); let mut dp = vec![vec![vec![None; n + 1]; n]; n]; process(&s1, &s2, 0, 0, n, &mut dp) } fn process( s1: &[char], s2: &[char], left1: usize, left2: usize, size: usize, dp: &mut Vec<Vec<Vec<Option<bool>>>>, ) -> bool { if let Some(item) = dp[left1][left2][size] { return item; } let mut res = false; if size == 1 { res = s1[left1] == s2[left2]; } else { for i in 1..size { if (process(s1, s2, left1, left2, i, dp) && process(s1, s2, left1 + i, left2 + i, size - i, dp)) || (process(s1, s2, left1, left2 + size - i, i, dp) && process(s1, s2, left1 + i, left2, size - i, dp)) { res = true; break; } } } dp[left1][left2][size] = Some(res); res } fn main() { let mut s1 = String::new(); let mut s2 = String::new(); let stdin = std::io::stdin(); let _ = stdin.read_line(&mut s1); let _ = stdin.read_line(&mut s2); let res = is_scramble(s1.trim().to_string(), s2.trim().to_string()); println!("{}", if res {"YES"} else {"NO"}); }
#include<cstdio> #include<cstring> #include<map> using namespace std; map<char,int> m; int dp[110][110][110]; bool issameele(char str1[],char str2[]){ int len1=strlen(str1); int len2=strlen(str2); if(len1!=len2) return false; for(int i=0;i<len1;++i){ m[str1[i]]++; } for(int i=0;i<len2;++i){ if(--m[str2[i]]<0) return false; } return true; } int main(){ char str1[110],str2[110]; while(scanf("%s %s",str1,str2)!=EOF){ m.clear(); int len=strlen(str1); if(!issameele(str1,str2)) { printf("NO\n"); continue; } memset(dp,sizeof(dp),0); for(int l=1;l<=len;++l){ for(int i=0;i<=len-l;++i){ for(int j=0;j<=len-l;++j){ if(l==1) { dp[i][j][l]=(str1[i]==str2[j]?1:0); continue; } for(int k=1;k<l;++k){ if(dp[i][j][k]&&dp[i+k][j+k][l-k]||dp[i][j+l-k][k]&&dp[i+k][j][l-k]) { dp[i][j][l]=1; break; } } } } } if(dp[0][0][len]==1) printf("YES\n"); else printf("NO\n"); } return 0; } #include<cstdio> #include<cstring> #include<map> using namespace std; map<char,int> m; bool issameele(char str1[],char str2[]){ int len1=strlen(str1); int len2=strlen(str2); if(len1!=len2) return false; for(int i=0;i<len1;++i){ m[str1[i]]++; } for(int i=0;i<len2;++i){ if(--m[str2[i]]<0) return false; } return true; } bool dfs(char str1[],char str2[],int l1,int l2,int len){ if(len==1) return str1[l1]==str2[l2]; for(int i=1;i<len;++i){ if(dfs(str1,str2,l1,l2,i)&&dfs(str1,str2,l1+i,l2+i,len-i)||dfs(str1,str2,l1,l2+len-i,i)&&dfs(str1,str2,l1+i,l2,len-i)) return true; } return false; } int main(){ char str1[110],str2[110]; while(scanf("%s %s",str1,str2)!=EOF){ m.clear(); int len=strlen(str1); if(!issameele(str1,str2)) { printf("NO"); continue; } if(dfs(str1,str2,0,0,len)) printf("YES\n"); else printf("NO\n"); } }
#include <iostream> #include <string> using namespace std; int main() { string str1,str2; cin >> str1; cin >> str2; if(str1.size() != str2.size()) { cout << "NO" <<endl; }else{ int i = 0,k = str1.size()-1; while(i < k) { if(str1[i++] == str2[k--]) { continue; } else{ cout << "NO" <<endl; return 0; } } } cout << "YES" <<endl; return 0; }