当前位置: 首页 > news >正文

字符串查找算法总结(暴力匹配、KMP 算法、Boyer-Moore 算法和 Sunday 算法)

字符串匹配是字符串的一种基本操作:给定一个长度为 M 的文本和一个长度为 N 的模式串,在文本中找到一个和该模式相符的子字符串,并返回该字字符串在文本中的位置。

KMP 算法,全称是 Knuth-Morris-Pratt 算法,以三个发明者命名,开头的那个K就是著名科学家 Donald Knuth 。KMP 算法的关键是求 next 数组。next 数组的长度为模式串的长度。next 数组中每个值代表模式串中当前字符前面的字符串中,有多大长度的相同前缀后缀。

Boyer-Moore 算法在实际应用中比 KMP 算法效率高,据说各种文本编辑器的"查找"功能(Ctrl+F),包括 linux 里的 grep 命令,都是采用 Boyer-Moore 算法。该算法有“坏字符”和“好后缀”两个概念。主要特点是字符串从后往前匹配。

Sunday 算法跟 KMP 算法一样,是从前往后匹配。在匹配失败时,关注文本串中参加匹配的最末位字符的下一位字符,如果该字符不在模式串中,则整个模式串移动到该字符之后。如果该字符在模式串中,将模式串右移使对应的字符对齐。

关于这几种算法的详细介绍,可参考该博客。

下面分别给出暴力匹配、KMP 算法、Boyer-Moore 算法和 Sunday 算法的 Java 实现。

暴力匹配:

public static int forceSearch(String txt, String pat) {
    int M = txt.length();
    int N = pat.length();
    for (int i = 0; i <= M - N; i++) {
        int j;
        for (j = 0; j < N; j++) {
            if (txt.charAt(i + j) != pat.charAt(j))
                break;
        }
        if (j == N)
            return i;
    }
    return -1;
}

KMP 算法:

public class KMP {
    public static int KMPSearch(String txt, String pat, int[] next) {
        int M = txt.length();
        int N = pat.length();
        int i = 0;
        int j = 0;
        while (i < M && j < N) {
            if (j == -1 || txt.charAt(i) == pat.charAt(j)) {
                i++;
                j++;
            } else {
                j = next[j];
            }
        }
        if (j == N)
            return i - j;
        else
            return -1;
    }

    public static void getNext(String pat, int[] next) {
        int N = pat.length();
        next[0] = -1;
        int k = -1;
        int j = 0;
        while (j < N - 1) {
            if (k == -1 || pat.charAt(j) == pat.charAt(k)) {
                ++k;
                ++j;
                next[j] = k;
            } else
                k = next[k];
        }
    }


    public static void main(String[] args) {
        String txt = "BBC ABCDAB CDABABCDABCDABDE";
        String pat = "ABCDABD";
        int[] next = new int[pat.length()];
        getNext(pat, next);
        System.out.println(KMPSearch(txt, pat, next));
    }
}

Boyer-Moore 算法

public class BoyerMoore {
    public static void getRight(String pat, int[] right) {
        for (int i = 0; i < 256; i++){
            right[i] = -1;
        }
        for (int i = 0; i < pat.length(); i++) {
            right[pat.charAt(i)] = i;
        }
    }

    public static int BoyerMooreSearch(String txt, String pat, int[] right) {
        int M = txt.length();
        int N = pat.length();
        int skip;
        for (int i = 0; i <= M - N; i += skip) {
            skip = 0;
            for (int j = N - 1; j >= 0; j--) {
                if (pat.charAt(j) != txt.charAt(i + j)) {
                    skip = j - right[txt.charAt(i + j)];
                    if (skip < 1){
                        skip = 1;
                    }
                    break;
                }
            }
            if (skip == 0)
                return i;
        }
        return -1;
    }

    public static void main(String[] args) {
        String txt = "BBC ABCDAB AACDABABCDABCDABDE";
        String pat = "ABCDABD";
        int[] right = new int[256];
        getRight(pat,right);
        System.out.println(BoyerMooreSearch(txt, pat, right));
    }
}

Sunday算法

public class Sunday {
    public static int getIndex(String pat, Character c) {
        for (int i = pat.length() - 1; i >= 0; i--) {
            if (pat.charAt(i) == c)
                return i;
        }
        return -1;
    }

    public static int SundaySearch(String txt, String pat) {
        int M = txt.length();
        int N = pat.length();
        int i, j;
        int skip = -1;
        for (i = 0; i <= M - N; i += skip) {
            for (j = 0; j < N; j++) {
                if (txt.charAt(i + j) != pat.charAt(j)){
                    if (i == M - N)
                        break;
                    skip = N - getIndex(pat, txt.charAt(i + N));
                    break;
                }
            }
            if (j == N)
                return i;
        }
        return -1;
    }
    public static void main(String[] args) {
        String txt = "BBC ABCDAB AACDABABCDABCDABD";
        String pat = "ABCDABD";
        System.out.println(SundaySearch(txt, pat));
    }
}

转载于:https://www.cnblogs.com/linbingdong/p/6479537.html

相关文章:

  • $$$$GB2312-80区位编码表$$$$
  • CFD使用者应当了解的一些事情
  • C# 进程同步,通信
  • 第三份CS地图--沙漠之战
  • 构建基于分布式SOA架构的统一身份认证体系
  • 傻瓜式Linux之三:安装软件
  • Python 3.5 socket OSError: [Errno 101] Network is unreachable
  • 华章1-2月份新书简介(2017年)
  • 专业网站打包/解包asp工具(E文精装版本)!
  • 【健康医疗】4步完成数据分析报表,让医疗数据转化为生产力
  • ORACLE查找并解除死锁进程
  • 云计算那些事
  • 推荐几本书给大家
  • javascript中this的用法
  • Foxmail邮件发不出去,都是Mcafee惹得祸
  • 【MySQL经典案例分析】 Waiting for table metadata lock
  • 【RocksDB】TransactionDB源码分析
  • 【vuex入门系列02】mutation接收单个参数和多个参数
  • Android优雅地处理按钮重复点击
  • CAP 一致性协议及应用解析
  • ComponentOne 2017 V2版本正式发布
  • CSS选择器——伪元素选择器之处理父元素高度及外边距溢出
  • golang 发送GET和POST示例
  • gulp 教程
  • Java 网络编程(2):UDP 的使用
  • Java编程基础24——递归练习
  • Java教程_软件开发基础
  • Mocha测试初探
  • mysql innodb 索引使用指南
  • React-Native - 收藏集 - 掘金
  • Sass Day-01
  • tensorflow学习笔记3——MNIST应用篇
  • vue-cli3搭建项目
  • vue学习系列(二)vue-cli
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 力扣(LeetCode)21
  • 算法之不定期更新(一)(2018-04-12)
  • 异常机制详解
  • 用quicker-worker.js轻松跑一个大数据遍历
  • 组复制官方翻译九、Group Replication Technical Details
  • ​【C语言】长篇详解,字符系列篇3-----strstr,strtok,strerror字符串函数的使用【图文详解​】
  • ​linux启动进程的方式
  • ​卜东波研究员:高观点下的少儿计算思维
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • #考研#计算机文化知识1(局域网及网络互联)
  • %check_box% in rails :coditions={:has_many , :through}
  • (Forward) Music Player: From UI Proposal to Code
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (三)uboot源码分析
  • (转)甲方乙方——赵民谈找工作
  • .FileZilla的使用和主动模式被动模式介绍
  • .Net 8.0 新的变化
  • .NET Core IdentityServer4实战-开篇介绍与规划