字符串匹配问题 算法

暴力

import java.util.Scanner;

public class trybaoLi22_3 {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("请输入第一个字符串:");
        String S1 = input.nextLine();
        System.out.println("请输入第二个字符串:");
        String S2 = input.nextLine();

        int index = match(S1, S2);
        if (index >= 0) {
            System.out.println(index);
        } else {
            System.out.println("No search");
        }
    }

    public static int match(String S1, String S2) {
        for (int i = 0; i < S1.length() - S2.length() + 1; i++) {
            if (isMathed(i, S1, S2)) {
                return i;
            }
        }
        return -1;
    }

    public static boolean isMathed(int i, String S1, String S2) {
        for (int k = 0; k < S2.length(); k++) {
            if (S2.charAt(k) != S1.charAt(i + k)) {
                return false;
            }
        }
        return true;
    }

KMP

JAVA语言程序设计第22章第3题  22.3

import java.util.Scanner;

public class tryKMP22_3B {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("请输入第一个字符串:");
        String S1 = input.nextLine();
        System.out.println("请输入第二个字符串:");
        String S2 = input.nextLine();

        int index = KPM(S1, S2);
        if (index >= 0) {
            System.out.println(index);
        } else {
            System.out.println("No search");
        }
    }

    private static int KPM(String S1, String S2) {
        int[] fail = getFailure(S2);
        int i = 0;// index on S1
        int j = 0;// index on S2
        while (i< S1.length())
            if(S1.charAt(i) == S2.charAt(j)){
                if(j==S2.length()-1){
                    return i-S2.length()+1; // S2 mathcd
                }
                i++;
                j++;
            }else{
                if(j>0){
                    j= fail[j-1];
                }
                else{
                    i++;
                }
            }
        return -1;
    }
    public static int[] getFailure(String S2){
        int[] fail = new int[S2.length()];
        int i = 1;
        int k = 0;
        while(i<S2.length()){
            if(S2.charAt(i)==S2.charAt(k)){
                fail[i] = k+1;
                i++;
                k++;
            }else if (k>0){
                k=fail[k-1];
            }else{
                i++;
            }
        }
        return fail;
    }

 

 

我的改进的KMP更易看懂

import java.util.Arrays;
import java.util.Scanner;

public class tryKMP22_3I {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("请输入第一个字符串:");
        String S1 = input.nextLine();
        System.out.println("请输入第二个字符串:");
        String S2 = input.nextLine();

        int index = KPM(S1, S2);
        if (index >= 0) {
            System.out.println(index);
        } else {
            System.out.println("No search");
        }
    }

    // KMP方法查找 匹配字符串
    private static int KPM(String S1, String S2) {
        int[] next = nextCreat(S2);
        int yiPiPei = 0;
        for (int i = 0, j = 0; i < S1.length(); i++) {
//            while (j > 0 && S1.charAt(i) != S2.charAt(j)) {  // 不匹配
            if (j > 0 && S1.charAt(i) != S2.charAt(j)) {  // 不匹配
                j = next[j - 1]; // 找到前面 对应的部分匹配值
//                System.out.println(" " + i + " "+ j);
                i = i + yiPiPei - j; // 移动位数  = 已匹配的字符数 - 对应的部分匹配值
//                System.out.println(i);
                yiPiPei = 0; // 已经没有 一匹配的字符数了
            }
            if (S1.charAt(i) == S2.charAt(j)) { // 匹配
                j++;
                yiPiPei = j; // 匹配个数同步
            }
            if (j == S2.length()) {
                return i - j + 1;
            }
        }
        return -1;
    }
    // 创建字符串的next数组
    //
    // 在暴力算法的基础上通过next数组回溯 j 来减少时间复杂度
    //
    // 移动位数 = 已匹配的字符数 - 对应的部分匹配值

// "部分匹配"的实质是,有时候,字符串头部和尾部会有重复。
// 比如,"ABCDAB"之中有两个"AB",那么它的"部分匹配值"就是2("AB"的长度)。
// 搜索词移动的时候,第一个"AB"向后移动4位(字符串长度-部分匹配值),就可以来到第二个"AB"的位置。


    // 这个方法可以找出 部分匹配表
    private static int[] nextCreat(String S2) {
        int[] next = new int[S2.length()];
        next[0] = 0;
        // i 是源字符串下标    j 是
        for (int i = 1, j = 0; i < S2.length(); i++) {
            while (j > 0 && S2.charAt(i) != S2.charAt(j)) {// 不匹配
                j = next[j - 1];  // 回溯收回
            }
            if (S2.charAt(i) == S2.charAt(j)) { // 匹配成功
                j++; //
            }
            next[i] = j;
        }
        System.out.println(Arrays.toString(next));
        return next;
    }
    // 初始化next数组
    //
    // 前后缀不相同的情况:j重复回退j=next[j-1],直到j==0或前后缀相同
    //
    // 前后缀相同情况:j++
    //
    // 给next数组赋值next[i]=j

Boyer-Moore

import java.util.Scanner;

public class Boyer_Moore {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("请输入第一个字符串:");
        String S1 = input.nextLine();
        System.out.println("请输入第二个字符串:");
        String S2 = input.nextLine();

        int index = BoM(S1, S2);
        if (index >= 0) {
            System.out.println(index);
        } else {
            System.out.println("No search");
        }
    }

    public static int BoM(String S1, String S2) {
        int i = S2.length() - 1;   // 总的固定的
        while (i < S1.length()) {
            int j = S2.length() - 1;  // 索引S2
            int k = i;            // 索引S1
            while (j >= 0) {
                if (S1.charAt(k) == S2.charAt(j)) {
                    j--;
                    k--;
                } else {
                    break;
                }
            }
            if (j < 0)
                return k+1;
            int h = huaDong(j - 1, S2, S1.charAt(k));
            if (h > 0) {
                i = i + h;
            } else if (h < 0) {
                i = i + S2.length();
            } else {
                i = i + 1;
            }
        }
        return -1;
    }

    public static int huaDong(int j, String S2, char wei) {
        int weiZhi = 0;
//        System.out.println(wei + " " + j);
        while (j >= 0) {
            if (wei == S2.charAt(j)) {
                return weiZhi;
            }
            j--;
            weiZhi++;
        }
        return -1;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你这个年纪你是怎么睡得着的

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值