第三章 3.1 字符串移位包含的问题
问题详细描述:
给定两个字符串s1和s2,要求判断s2是否能够被s1做循环移位得到的字符串包含。
输入输出示例:
给定s1=”AABCD”和s2=”CDAA”,返回true;
给定s1=”ABCD”和s2=”ACBD”,返回false。
对于编程之美中使用C语言的解法请参见这一篇文章,讲的很详细
地址:字符串移位包含的问题 – 丫坏孩子 – 博客园
下面是我的Java版本的解法,其中用到了KMP模式匹配算法,不懂的可以去看看我之前的一篇,
地址:Java数据结构-串及其应用-KMP模式匹配算法 | Pan Hai nan’Blog
里面推荐了怎么学习KMP模式匹配算法。
下面贴上我的代码:StringRotate.java
package com.chapter.third;
/**
* @author phn
* @TODO 字符串移位包含的问题
* 问题详细描述:
* 给定两个字符串s1和s2,要求判断s2是否能够被s1做循环移位得到的字符串包含。
* 输入输出示例:
* 给定s1="AABCD"和s2="CDAA",返回true;
* 给定s1="ABCD"和s2="ACBD",返回false。
*/
public class StringRotate {
/**
* @TODO 蛮力法解题:通过对s1循环移位,直接进行判断
* @param srcChar
* @param desChar
* @return true or false
*/
public static boolean rotate0(char []srcChar,char []desChar){
for(int i=0;i<srcChar.length;i++){
//这里调用KMP模式匹配算法进行判断是否包含问题
//返回-1表示不包含,返回其他表示包含且首地址为返回值。
if(FOKMP.indexKMP(srcChar, desChar)!=-1){
return true;
}
char tempChar = srcChar[0];
//这里做循环移位
for(int j = 0;j<srcChar.length-1;j++){
srcChar[j] = srcChar[j+1];
}
srcChar[srcChar.length-1] = tempChar;
}
return false;
}
/**
* @TODO 通过将s1转化为s1s1,判断s1s1是否包含s2来得出问题的解(空间换时间)
* @param srcChar
* @param desChar
* @return true or false
*/
public static boolean rotate1(char []srcChar,char []desChar){
char []doubleSrcChar = new char[2*srcChar.length];
//将两个srcChar连接变成doubleSrcChar
for(int i = 0; i<2*srcChar.length; i++){
doubleSrcChar[i] = srcChar[i%srcChar.length];
}
//这里调用KMP模式匹配算法进行判断是否包含问题
//返回-1表示不包含,返回其他表示包含且首地址为返回值。
if(FOKMP.indexKMP(doubleSrcChar, desChar)!=-1){
return true;
}
return false;
}
}
辅助类KMP模式匹配算法:FOKMP.java
package com.chapter.third;
/**
* @author 潘海南
* @Email 1016593477@qq.com
* @TODO 模式匹配算法
*/
public class FOKMP {
private static int[] getNext(char []Str) {
int[] next = new int[Str.length];
int i, j;
i = 0;
j = -1;
next[0] = -1;
while (i < Str.length - 1) {
if (j == -1 || Str[i] == Str[j]) {
i++;
j++;
if (Str[i] != Str[j]) {
next[i] = j;
} else {
next[i] = next[j];
}
} else {
j = next[j];
}
}
return next;
}
public static int indexKMP(char []S, char []T) {
int i = 0;
int j = 0;
int[] next = getNext(T);
while (i <= S.length - 1 && j <= T.length - 1) {
if (j == -1 || S[i] == T[j]) {
i++;
j++;
} else {
j = next[j];
}
}
if (j >= T.length)
return i - T.length;
return -1;
}
}
测试方法:
public static void main(String[] args) {
System.out.println("rotate0:"+rotate0("ABCD".toCharArray(),"ACBD".toCharArray()));
System.out.println("rotate1:"+rotate1("ABCD".toCharArray(),"ACBD".toCharArray()));
System.out.println("rotate0:"+rotate0("AABCD".toCharArray(),"CDAA".toCharArray()));
System.out.println("rotate1:"+rotate1("AABCD".toCharArray(),"CDAA".toCharArray()));
}