KMP的使用——我的总结

  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 }

 

posted @ 2018-05-15 17:29  郭流水  阅读(438)  评论(0编辑  收藏  举报