KMP模式匹配算法学习记录

本文探讨了在字符串匹配问题中,如何使用Java内置函数与KMP算法来寻找模式在文本中的首次出现位置。通过示例代码展示了两种方法的实现,并指出在特定测试集上两者性能接近,但KMP算法理论上具有更好的时间复杂度。

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

串的匹配模式——如何进行串的匹配


一、匹配目标

给定一段文本:string = s0s1…sn-1

给定一个模式:pattern = p1p2…pm-1

求pattern在string中第一次出现的位置

二、算法

1.java库函数

int indexOf(String str)
int indexOf(String str, int fromIndex)

返回与字符串str匹配的第一个字串的开始位置。从索引0或fromIndex开始匹配。如果在原始字符串中不存在str,则返回-1。

代码如下(示例):

public class Main {
    public static void main(String[] args) throws Exception {
        String a = "This is a sample example";
        String b = "sample";
        int i = a.indexOf(b);
        System.out.println(i);
    }
}

运行结果如下:

10

2.KMP算法

时间复杂度T(n) = O(n + m),n为文本长度,m为模式长度

代码如下:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) throws Exception {
        Scanner scanner = new Scanner(System.in);
        String text = scanner.nextLine();
        int N = Integer.parseInt(scanner.nextLine());
        KMP kmp = new KMP();
        String output = "";
        for(int i = 0; i < N; i++){
            String pattern = scanner.nextLine();
            int position = kmp.KMP_exert(text, pattern);
            if(position != -1){
                output += text.substring(position) + "\n";
            }
            else{
                output += "Not Found" + "\n";
            }
        }
        scanner.close();
        int length = output.length();
        System.out.println(output.substring(0, length - 1));
    }
}

class KMP{
    private int NotFound = -1;
    private int[] match;

    private void buildMatch(String pattern){
        int i, j;
        int m = pattern.length();
        match[0] = -1;

        for(j = 1; j < m; j++){
            i = match[j - 1];
            while((i >= 0) && (pattern.charAt(i + 1) != pattern.charAt(j))){
                i = match[i];
            }
            if(pattern.charAt(i + 1) == pattern.charAt(j)){
                match[j] = i + 1;
            }
            else{
                match[j] = -1;
            }
        }
    }

    public int KMP_exert(String string, String pattern){
        int n = string.length();
        int m = pattern.length();
        int s, p;

        if(n < m){
            return NotFound;
        }
        match = new int[m];
        s = p = 0;
        buildMatch(pattern);
        while(s < n && p < m){
            if(string.charAt(s) == pattern.charAt(p)){
                s++;
                p++;
            }
            else if(p > 0){
                p = match[p - 1] + 1;
            }
            else{
                s++;
            }
        }
        if(p == m){
            return s - m;
        }
        else{
            return NotFound;
        }
    }
}



总结

在PTA测试集上运行结果是两个算法的速度差不多,可能需要更大的测试集且更宽松的测试时间才能体现出算法二的优越性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值