编程之美-字符串移位包含的问题

第三章 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()));
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值