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 }