今天在算法4中看到了一个回环变位,觉得好高大上,由于才开始学习的算法,我也是抱着虚心学习的态度,打算实现一下,顺便看到了2017校招一模的第二个编程题就是回环变位的变形,下面细说一二。
题目是这样滴:
如果字符串s中的字符循环转移任意位置之后得到一个新的字符串t,那么s就被称为t的回环变位(circular rotation),例如ACTGACG就是TGACGAC的一个回环变位,反之亦然判定这个条件在基因组序列的研究中是很重要的,编写一个程序检查给定的字符串s和t是否互为回环变位
提示:答案只需要一行用到index(),length()和字符串连接的代码
由于对java字符串API不是十分了解,所以先想到了拆分遍历再合并的方法。
今天在牛客中学习了一会,我的两种方法的实现:
*第一种方法是:将一个字符串写两遍,比如else,写两遍elseelse,则取定长的4位为所有的变换子循环单词。 即else,lsee,seel,eels
package com.niuke.algorithms;
/**
* @author 康师傅没有眼泪
* @data 2017年6月6日 上午12:07:23
* 第二种方法是想将字符串写两次,定长截取做判断
* (s.length() == t.length()&&(s.concar(s).indexOf()))
*/
public class StringOperationDemo {
public static void main(String args[]){
String s1 = "actgacg";
String s2 = "tgacgac";
if(s1.length() == s2.length() && (s1.concat(s1).indexOf(s2)) >=0 )
System.out.println("s1,s2互为回环变位");
else
System.out.println("s1,s2不是回环变位");
}
}
*第二种方法是:把字符串最右边的的字符移动到最左边
即eels,一个循环右移即可。
package com.niuke.algorithms;
/**
* @author 康师傅没有眼泪
* @data 2017年6月4日 下午5:52:16
* 只用到一行的代码实现
* (s.length() == t.length()&&(s.concar(s).indexOf())) 我很无语
*/
public class CircularRotation {
public static void main(String args[]){
String s1 = "word";
String s2 = "ordw";
if(isCircularRotation(s1,s2)){
System.out.println("s1,s2互为回环变位");
}else{
System.out.println("s1,s2不是互为回环变位");
}
}
public static boolean isCircularRotation(String s,String t){
if(s.length() != t.length()){
return false;
}else{
for(int i = 1; i <= s.length(); i++){
String left = s.substring(0, i);
String right = s.substring(i, s.length());
if((right+left).equals(t)){
return true;
}
}
}
return false;
}
}
2017校招一模的第二个编程题就是回环变位的变形
题目是这样滴: 如果一个单词通过循环右移获得的单词,我们称这些单词都为一种循环单词。 例如:picture 和 turepic
就是属于同一种循环单词。 现在给出n个单词,需要统计这个n个单词中有多少种循环单词。 输入描述: 输入包括n+1行:
第一行为单词个数n(1 ≤ n ≤ 50) 接下来的n行,每行一个单词word[i],长度length(1 ≤ length ≤
50)。由小写字母构成输出描述: 输出循环单词的种数
输入例子: 5 picture turepic icturep word ordw
输出例子: 2
以下为代码实现:
package com.stringoperation.algorithms;
import java.util.ArrayList;
import java.util.Scanner;
/**
* @author 康师傅没有眼泪
* @data 2017年6月4日 下午6:15:53
*
*/
public class MainTest {
public static void main(String[] args) {
int N=50;
Scanner sc = new Scanner(System.in);
N = sc.nextInt(); //第一行为单词个数N
ArrayList<String> list = new ArrayList<>();
int count = 0;
for (int i = 0; i < N; i ++) {
String s = sc.next(); //输入并存储每行的单词。此处必须调用next()方法
if (!list.contains(s)) {
count ++;
list.add(s);
for (int j = 0; j < s.length() - 1; j ++) {
//以下注释是另一种方法,把可能的循环单词加入list,
//思路:把要测试的单词后再重复下这个单词,如:word ,变成 wordword
String st r = new String();
str = s.concat(s);
/* str.append(s);
sb.insert(sb.length(), x) 都可实现,用StringBuffer类即可实现
str.append(s); sb.insert(sb.length(), x) */
String b = str.substring(j, s.length() + j);
list.add(b);
}
}
}
System.out.println(count);
}
}
最后附上已知字符串S逆序的递归实现方式
public static String mystery(String s){
int N=s.length();
String s1 = s.substring(0, N/2);
String s2 = s.substring(N/2, N);
return mystery(s2) + mystery(s1);
}