1 // KMP.cpp : 定义控制台应用程序的入口点。
2 //
3
4 #include "stdafx.h"
5 #include <iostream>
6 #include <new>
7 using namespace std;
8
9 /************************************************************************
10 这个算法的关键在于不用回溯指示主串当前比较位置的变量i,
11 当主串和模式串失配时,只需要将模式串向右滑动尽可能大的距离
12 即决定主串当前位置i上的元素 应该和 模式串的哪个元素比较
13 即关键在于求的一个next[j]数组,当主串在i位置和模式串的j位置失配时,
14 应该将模式串的next[j]位置元素和主串i位置元素开始比较,重复此过程
15
16 所以问题的关键在于求解一个next[j]数组,这个数组的求解是和主串无关的。
17
18 ************************************************************************/
19
20 //以下代码并没有完全的对参数进行检查
21
22 //求解next数组
23 //lpString为模式串
24 //next为输入数组
25 void GetNext(const TCHAR* lpString, int* next)
26 {
27 if (NULL == lpString || NULL == next){ return; }
28 int j = 0;
29 int k = 0;
30 next[0] = -1;
31 j = 0;
32 k = -1;
33
34 int length = _tcslen(lpString);
35 while (j < length - 1)
36 {
37 if (-1 == k || lpString[j] == lpString[k])
38 {
39 ++j;
40 ++k;
41 next[j] = k;
42 }
43 else
44 {
45 k = next[k];
46 }
47 }
48 }
49
50
51 int KMPMatch(const TCHAR* lpMain, const TCHAR* lpMatch)
52 {
53 int nMain = _tcslen(lpMain);
54 int nMatch = _tcslen(lpMatch);
55 int* pNext = new int[nMatch]();
56 int i = 0;
57 int j = 0;
58
59 if (NULL == pNext)
60 {
61 return -1;
62 }
63
64 GetNext(lpMatch, pNext);
65 while (i < nMain && j < nMatch)
66 {
67 if (-1 == j || lpMain[i] == lpMatch[j])
68 {
69 ++i; ++j;
70 }
71 else
72 {
73 j = pNext[j];
74 }
75 }
76
77 delete[] pNext;
78 pNext = NULL;
79
80 if (j >= nMatch)
81 {
82 return i - nMatch;
83 }
84
85 return -1;
86 }
87
88 int _tmain(int argc, _TCHAR* argv[])
89 {
90 const TCHAR* lpMain = _T("helloworld");
91 const TCHAR* lpMatch = _T("oworl");
92
93 wcout<<"模式串 "<<lpMatch<<" 在主串 "<<lpMain<<" 中的位置为 "
94 <<KMPMatch(lpMain, lpMatch)<<endl;;
95
96 return 0;
97 }
执行结果如下: