串的模式匹配
串的模式匹配也叫查找定位,指的是在当前串中寻找模式串的过程。主要的模式匹配算法有 Brute-Force 算法 和 KMP 算法;
Brute-Force 算法
Brute-Force 算法从主串的第一个字符开始和模式串的第一个字符进行比较,若相等,则继续比较后续字符;否则从主串的第二个字符开始重新和模式串进行比较。依次类推,直到模式串的每个字符依次与主串的字符相等,匹配成功;
//从位序号为begin的字符开始搜索与str相等的子串
public int BF(String str, int begin) throws Exception {
if(str.length()<=curLen&&str!=null&&curLen>0){
int i=begin;
int len=str.length();
while(i<=curLen-len){//从主串的第i个元素开始比较
for(int j=0;j<len;j++){//比较模式串的元素
if(str.charAt(j)!=strValue[j+i]){
i++;
break; //跳出当前循环
}
else if(j==len-1){//len个字符全部匹配成功
return i;
}
}
}
}
return -1;
}
Brute-Force 算法的实现简单,但效率非常低。
测试:
public class A {
private char[] strValue;//字符数组存放串值
private int curLen;//当前串的长度
//构造空串
public A(){
strValue=new char[0];
curLen=0;
}
//以字符串常量构造串
public A(String str){
char[] p=str.toCharArray();
strValue=p;
curLen=p.length;
}
//从位序号为begin的字符开始搜索与str相等的子串
public int BF(String str, int begin) throws Exception {
if(str.length()<=curLen&&str!=null&&curLen>0){
int i=begin;
int len=str.length();
while(i<=curLen-len){//从主串的第i个元素开始比较
for(int j=0;j<len;j++){//比较模式串的元素
if(str.charAt(j)!=strValue[j+i]){
i++;
break; //跳出当前循环
}
else if(j==len-1){//len个字符全部匹配成功
return i;
}
}
}
}
return -1;
}
public static void main(String[] args) throws Exception{
A aa =new A("ssdfgasdbababa");
int result = aa.BF("fg", 0);
System.out.println(result); //输出3
}
}
KMP 算法
因此我们需要:
- 取得目标字符串的匹配值数组next[];
- 根据next[]数组实现KMP算法;
求数组next[]:
public static int[] kmpnext(String dest){
int[] next = new int[dest.length()];
next[0] = 0;
for(int i = 1,j = 0; i < dest.length(); i++){
while(j > 0 && dest.charAt(j) != dest.charAt(i)){
j = next[j - 1];
}
if(dest.charAt(i) == dest.charAt(j)){
j++;
}
next[i] = j;
}
return next;
}
KMP实现:
public static int kmp(String str, String dest,int[] next){//str文本串 dest 模式串
for(int i = 0, j = 0; i < str.length(); i++){
while(j > 0 && str.charAt(i) != dest.charAt(j)){
j = next[j - 1];
}
if(str.charAt(i) == dest.charAt(j)){
j++;
}
if(j == dest.length()){
return i-j+1;
}
}
return 0;
}
测试:
public static void main(String[] args){
//String a = "ababa"; 输出9 0 0 1 2 3
// String b = "ssdfgasdbababa";
String a = "dfg"; //输出2 0 0 0
String b = "ssdfgasdbababa";
int[] next = kmpnext(a);
int res = kmp(b, a,next);
System.out.println(res);
for(int i = 0; i < next.length; i++){
System.out.println(next[i]);
}
}
以上的内容来自51CTO学院的数据结构课程,我只是整理了一下以便日后方便复习,如有侵权我会自行删除;
原文:http://edu.51cto.com/center/course/lesson/index?id=68078
挺好理解的,讲师讲的很通熟易懂,想学习的可以去看原版视频;