标签:
KMP是一种字符串模式匹配算法,在目标串中查找模式串的方法。
朴素查找方法在遇到目标串字串具备大量重复前缀且和模式串大部分吻合,其时间复杂度就会衰退为o(N*M),严格来说是o((N-M+1)*M)。
因此,在数据量很大的时候我们需要一种线性复杂度的算法。
KMP的优势是通过next数组记录了目标串从0~i-1位之前的最长重复前后缀的长度,当出现失配情况时,不像朴素算法那样返回模式串的初始位置,而是根据模式串失配之前的位匹配成功的特性,返回失配位前最长重复前缀长度在模式串的位置。
模板题 HDU-2087 剪花布条
1 #include <iostream> 2 #include <string> 3 #include <cstring> 4 #define N 1005 5 using namespace std; 6 int nex[N];//用于存放第i位之前的最长重复前缀长度 7 string a,val;//a:目标串 val:模式串 8 void getNext() 9 { 10 int len = a.length(); 11 int i = 0,j = -1; 12 nex[0]=-1;//因为数组从0开始,所以-1代表了i位之前的最长重复前后缀位置不存在 13 while (i !=a.size()-1 ) 14 { 15 if (j == -1 || a[i] == a[j])//当j为-1时,直接匹配,因为单个字符一定是自我重复的 16 i++, j++, nex[i] = j; 17 else 18 j = nex[j];//next数组生成过程也是一个匹配过程,所以失配时利用之前的next来寻找转移位置 19 } 20 } 21 22 int kmp(int st)//从目标串st位置开始查找模式串,查找过程和next生成过程极为相似,不过多赘述 23 { 24 int lena = a.length(); 25 int lenv = val.length(); 26 int i = st, j = 0; 27 while (i < lena&&j<lenv) 28 { 29 if (j==-1||a[i] == val[j]) 30 i++, j++; 31 else 32 j = nex[j]; 33 34 } 35 return j == val.length() ? i : -1;//当模式串查找到结尾,说明在目标串中查找到了完整的字串,返回值根据需求而定 36 } 37 int main() { 38 while (cin >> a) 39 { 40 if (a[0] == ‘#‘) 41 break; 42 cin >> val; 43 int idx = 0, ans = 0; 44 getNext(); 45 int len = a.length(); 46 while (idx < a.length()) 47 { 48 int jmp = kmp(idx); 49 if (jmp == -1) 50 break; 51 else 52 { 53 ans++; 54 idx = jmp; 55 } 56 } 57 cout << ans << endl; 58 } 59 return 0; 60 }
若上文出现任何错误请及时指出,感谢!
标签:
原文地址:http://www.cnblogs.com/LukeStepByStep/p/5774910.html