1 /*
2 descr: 求KMP的next数组
3 param: p 模式串指针
4 param: nLeng 模式串有效字符长度
5 param: next 存放next值的数组,长度为nLeng+1
6 */
7 void initNextArray(char* p, int nLeng, int* next)
8 {
9 next[0] = nLeng;
10
11 do {
12
13 if (1== nLeng)
14 {
15 next[1] = 0;
16 break;
17 }
18
19 if (2 == nLeng)
20 {
21 next[1] = 0;
22 next[2] = 1;
23 break;
24
25 }
26
27 int k = 0;
28
29 next[1] = 0;
30 next[2] = 1;
31
32 k = next[3 - 1];
33
34 for (int i = 3; i <= nLeng; )
35 {
36
37 if ( p[i-1] ==p[k])
38 {
39 ++k; //说明前k个字符与当前i前面的k个字符完全匹配
40 next[i] = k; //说明当前i前面有k个字符是与最前面的k个字符是相同的
41 ++i; //继续往后比较
42 }
43 else if (1 == k)
44 {
45 k = 1; //已经比较到第一个字符了,故k=1
46 next[i] = k;
47 ++i;
48 }
49 else
50 {
51 k = next[k];
52 //此时i不需要动,继续往前找出现k个相同字符的位置
53 }
54
55 }
56
57
58 } while (0);
59
60 for (int i = 1; i <= nLeng; i++)
61 {
62 std::cout << next[i] << " ";
63 }
64
65 std::cout << endl;
66
67 }
68
69 int KMP_Search(char* pMain, char* pSub)
70 {
71
72
73 int nIndex = 0;
74
75 int nMainLen = strlen(pMain);
76
77 int nLen = strlen(pSub);
78
79
80 char* pMain_bk = new char[nMainLen + 2];
81 memset(pMain_bk, 0, nMainLen + 2);
82
83 pMain_bk[0] = ' ';
84 memcpy(&pMain_bk[1], pMain, nMainLen);
85
86
87 char* pSub_bk = new char[nLen + 2];
88 memset(pSub_bk, 0, nLen + 2);
89
90 pSub_bk[0] = ' ';
91 memcpy(&pSub_bk[1], pSub, nLen);
92
93 int * next = new int[nLen+1];
94 memset(next, 0, nLen+1);
95
96 initNextArray(pSub_bk, nLen, next);
97
98 int i = 1, k = 1; //从下标1开始匹配
99 //下标从1开始
100 for (; i <= nMainLen && k<= nLen; )
101 {
102
103 if (0 == k)
104 {
105 //当前字符不匹配,且k=0,说明已经比较到第一个字符了,
106 //则需要重新从第一个字符跟当前主串的后一个字符进行比较
107 k = 1;
108 ++i;
109 }
110 else if (pMain_bk[i] == pSub_bk[k])
111 {
112 ++k;
113 ++i; //当前字符匹配,则继续
114 }
115 else
116 {
117 k = next[k]; //退回合适的位置,i不变
118 }
119 }
120
121 if (k > nLen)
122 {
123 nIndex = i - nLen;
124 }
125
126 return nIndex;
127
128 }
129
130 void test_KMP()
131 {
132 char szMain[] = "12345Hello789";
133 char szSub[] = "Hello";
134
135 int nIndex = KMP_Search(szMain, szSub);
136
137 std::cout << "1, nIndex=" << nIndex << endl;
138
139 char szMain2[] = "12345Hello789";
140 char szSub2[] = "456";
141
142 nIndex = KMP_Search(szMain2, szSub2);
143
144 std::cout << "2, nIndex=" << nIndex << endl;
145
146 char szMain3[] = "ababaabca";
147 char szSub3[] = "abc";
148
149 nIndex = KMP_Search(szMain3, szSub3);
150
151 std::cout << "3, nIndex=" << nIndex << endl;
152
153
154 }
155
156 int main(void)
157 {
158 test_getNext();
159
160 getchar();
161 }