模式匹配算法
Posted flow-wangqi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模式匹配算法相关的知识,希望对你有一定的参考价值。
1、基本概念:
目标串:s
模式串:t
模式串第 j 个元素 :t[j]
2、BF算法:
通过将目标串S的第一个字符与模式串T的第一个字符进行匹配,若相等,则继续比较S的第二个字符和 T的第二个字符;若不相等,则比较S的第二个字符和T的第一个字符,依次比较下去,直到得出最后的匹配结果。BF算法是一种蛮力算法。
3、KMP算法:
通过利用已经部分匹配这个有效信息,保证 i 指针不回溯,通过修改 j 指针,让模式串尽量移动到有效位置。其中这个有效信息指的就是 next 数组和 nextval 数组。
3.1 next 数组手工求法
文字描述:
这里规定 next[0] = -1 ;
对于 next[j] ,考虑 j 之前的串,找出前缀和后缀相同的最长字串,设长度为 k ,则 next[j] = k 。
实例:
模式串 t : abcaba
比如求 next[5] ,考虑 abcab ,易知前缀和后缀相同的最长字串为 ab ,其长度为 2 ,故 next[5] = 2 。
3.2 nextval 数组手工求法
文字描述:
这里同样规定 nextval[0] = -1;
若 t[j] = t[next[j]] ,则 nextval[j] = nextval[next[j]] ,否则保持不变。
实例:
j | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
模式 t | a | b | c | a | b | a | a |
next[j] | -1 | 0 | 0 | 0 | 1 | 2 | 1 |
nextval[j] | -1 | 0 | 0 | -1 | 0 | 2 | 1 |
比如求 nextval[4] ,首先 t[4] = b = t[next[4]] = t[1] ,则 nextval[4] = nextval[next[4]] = nextval[1] = 0 ;
求 nextval[5] ,首先 t[5] = a == c = t[next[5]] = t[2] ,则 nextval[5] = next[5] = 2 。
4、完整代码及运行结果
苦逼的代码:
1 #include<stdio.h> 2 #include <string.h> 3 #define MaxSize 50 4 typedef char ElemType; 5 6 typedef struct { 7 ElemType data[MaxSize]; 8 int length; 9 } SqString; 10 11 //BF 算法 12 int BFIndex(SqString s, SqString t) { 13 int i = 0, j = 0; 14 while(i < s.length && j < t.length) { 15 if (s.data[i] == t.data[j]) { 16 i++; 17 j++; 18 } else { 19 //目标串 s 指针 i 和模式串 t 指针 j 同步后移 20 i = i - j + 1; 21 j = 0; 22 } 23 } 24 if (j >= t.length) { 25 return i - t.length; 26 } else { 27 return -1; 28 } 29 } 30 31 //计算 next 数组 32 void GetNext(SqString t, int next[]) { 33 int j = 0, k = -1; 34 next[0] = -1; 35 while(j < t.length) { 36 if (k == -1 || t.data[j] == t.data[k]) { 37 j++; 38 k++; 39 next[j] = k; 40 } else { 41 k = next[k]; 42 } 43 } 44 } 45 //依据 next 数组实现的 KMP 算法 46 int KMPIndex(SqString s, SqString t) { 47 int i = 0, j = 0; 48 int next[MaxSize]; 49 GetNext(t, next); 50 while(i < s.length && j < t.length) { 51 if (j == -1 || s.data[i] == t.data[j]) { 52 i++; 53 j++; 54 } else { 55 //模式串 t 指针 j 后移 56 j = next[j]; 57 } 58 } 59 if (j >= t.length) { 60 //返回模式串 t 所在位置物理下标 61 return i - t.length; 62 } else { 63 //匹配失败返回 -1 64 return -1; 65 } 66 } 67 68 //计算 nextval 数组 69 void GetNextval(SqString t, int nextval[]) { 70 int j = 0, k = -1; 71 nextval[0] = -1; 72 while(j < t.length) { 73 if (k == -1 || t.data[j] == t.data[k]) { 74 j++; 75 k++; 76 if (t.data[j] != t.data[k]) { 77 nextval[j] = k; 78 } else { 79 nextval[j] = nextval[k]; 80 } 81 } else { 82 k = nextval[k]; 83 } 84 } 85 } 86 //根据 nextval 数组实现的 KMP 算法 87 int KMPIndex1(SqString s, SqString t) { 88 int i = 0, j = 0; 89 int nextval[MaxSize]; 90 GetNextval(t, nextval); 91 while(i < s.length && j < t.length) { 92 if (j == -1 || s.data[i] == t.data[j]) { 93 i++; 94 j++; 95 } else { 96 //模式串 t 指针 j 后移 97 j = nextval[j]; 98 } 99 } 100 if (j >= t.length) { 101 //返回模式串 t 所在位置物理下标 102 return i - t.length; 103 } else { 104 //匹配失败返回 -1 105 return -1; 106 } 107 } 108 109 //将字符串数组赋值给 SqString 类型的字符串 110 void StrAssign(SqString &s, char csrt[]) { 111 int i; 112 for (i = 0; csrt[i] != ‘