第四十二课 KMP算法的应用

思考:

replace图解:

程序完善:

DTString.h:

 1 #ifndef DTSTRING_H
 2 #define DTSTRING_H
 3
 4 #include "Object.h"
 5
 6 namespace DTLib
 7 {
 8
 9 class String : Object
10 {
11 protected:
12     char* m_str;
13     int m_length;
14
15     void init(const char* s);
16     bool equal(const char* l, const char* r, int len) const;
17
18     static int* make_pmt(const char* p);
19     static int kmp(const char* s, const char* p);
20
21 public:
22     String();
23     String(char c);
24     String(const char* s);
25     String(const String& s);
26
27     int length() const;
28     const char* str() const;
29
30     bool startWith(const char* s) const;
31     bool startWith(const String& s) const;
32     bool endOf(const char* s) const;
33     bool endOf(const String& s) const;
34
35     String& insert(int i, const char* s);
36     String& insert(int i, const String& s);
37
38     String& trim();
39
40     int indexOf(const char* s) const;
41     int indexOf(const String& s) const;
42
43     String& remove(int i, int len); //删除指定下标,指定长度的子串
44     String& remove(const char* s);
45     String& remove(const String& s);
46
47     String& replace(const char* t, const char* s);
48     String& replace(const String& t, const char* s);
49     String& replace(const char* t, const String& s);
50     String& replace(const String& t, const String& s);
51
52     String sub(int i, int len) const;
53
54     char& operator [] (int i);
55     char operator [] (int i) const;
56
57     bool operator == (const String& s) const;
58     bool operator == (const char* s) const;
59
60     bool operator != (const String& s) const;
61     bool operator != (const char* s) const;
62
63     bool operator > (const String& s) const;
64     bool operator > (const char* s) const;
65
66     bool operator < (const String& s) const;
67     bool operator < (const char* s) const;
68
69     bool operator >= (const String& s) const;
70     bool operator >= (const char* s) const;
71
72     bool operator <= (const String& s) const;
73     bool operator <= (const char* s) const;
74
75     String operator + (const String& s) const;
76     String operator + (const char* s) const;
77     String& operator += (const String& s);
78     String& operator += (const char* s);
79
80     String operator - (const char* s) const;
81     String operator - (const String& s) const;
82     String& operator -= (const char* s);
83     String& operator -= (const String& s);
84
85     String& operator = (const String& s);
86     String& operator = (const char* s);
87     String& operator = (char c);
88
89     ~String();
90 };
91
92 }
93
94
95 #endif // DTSTRING_H

DTString.cpp:

  1 #include <cstring>
  2 #include <cstdlib>
  3 #include "DTString.h"
  4 #include "Exception.h"
  5
  6 using namespace std;
  7
  8 namespace DTLib
  9 {
 10
 11 int* String::make_pmt(const char* p)  // O(m)
 12 {
 13     int len = strlen(p);
 14
 15     int* ret = static_cast<int*>(malloc(sizeof(int) * len));
 16
 17     if( ret != NULL )
 18     {
 19         int ll = 0;
 20
 21         ret[0] = 0; // 第0个元素(长度为1的字符串)的ll值为0
 22
 23         for(int i = 1; i < len; i++)
 24         {
 25             //不成功的情况
 26             while( (ll > 0) && (p[ll] != p[i]) )
 27             {
 28                 ll = ret[ll];
 29             }
 30
 31             // 假设最理想的情况成立
 32             //在前一个ll值的基础行进行扩展,只需比对最后扩展的字符是否相等
 33             //相等的话ll值加1,并写入到部分匹配表
 34             if( p[ll] == p[i] )
 35             {
 36                 ll++;
 37             }
 38
 39             ret[i] = ll; // 将ll值写入匹配表
 40
 41         }
 42     }
 43
 44     return ret;
 45 }
 46
 47 int String::kmp(const char* s, const char* p)  //O(m) + O(n) = O(m + n)
 48 {
 49     int ret = -1;
 50
 51     int sl = strlen(s);
 52     int pl = strlen(p); //子串
 53
 54     int* pmt = make_pmt(p);   //O(m)
 55
 56     if( (pmt != NULL) && (0 < pl) && (pl <= sl))
 57     {
 58         for( int i = 0,j = 0; i < sl; i++ )
 59         {
 60             while( (j > 0) && (s[i] != p[j]) ) // j小于等于0时要退出
 61             {
 62                 j = pmt[j];
 63             }
 64
 65             if( s[i] == p[j] )
 66             {
 67                 j++;
 68             }
 69
 70             if( j == pl ) // j的值如果最后就是子串的长度,意味着查找到了
 71             {
 72                 ret = i + 1 - pl; // 匹配成功时i的值停在最后一个匹配的字符上
 73                 break;
 74             }
 75         }
 76     }
 77
 78     free(pmt);
 79
 80     return ret;
 81 }
 82
 83 void String::init(const char* s)
 84 {
 85     m_str = strdup(s);
 86
 87     if( m_str )
 88     {
 89         m_length = strlen(m_str);
 90     }
 91     else
 92     {
 93         THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create string object ...");
 94     }
 95 }
 96
 97 bool String::equal(const char* l, const char* r, int len) const
 98 {
 99     bool ret = true;
100
101     for(int i = 0; i < len && ret; i++)
102     {
103         ret = ret && (l[i] == r[i]);
104     }
105
106     return ret;
107 }
108
109 String::String()
110 {
111     init("");
112 }
113
114 String::String(const char* s)
115 {
116     init(s ? s : "");   //空指针就转换成空字符串
117 }
118
119 String::String(const String& s)
120 {
121     init(s.m_str);
122 }
123
124 String::String(char c)
125 {
126     char s[] = {c, ‘\0‘};
127
128     init(s);
129 }
130
131 int String::length() const
132 {
133     return m_length;
134 }
135
136 const char* String::str() const
137 {
138     return m_str;
139 }
140
141 bool String::startWith(const char* s) const
142 {
143     bool ret = ( s != NULL );
144
145     if( ret )
146     {
147         int len = strlen(s);
148
149         ret = (len < m_length) && equal(m_str, s, len);
150
151     }
152
153     return ret;
154 }
155
156 bool String::startWith(const String& s) const
157 {
158     return startWith(s.m_str);
159 }
160
161 bool String::endOf(const char* s) const
162 {
163     bool ret = ( s != NULL );
164
165     if( ret )
166     {
167         int len = strlen(s);
168
169         char* str = m_str + (m_length - len);
170
171         ret = (len < m_length) && equal(str, s, len);
172
173     }
174
175     return ret;
176 }
177
178 bool String::endOf(const String& s) const
179 {
180     return endOf(s.m_str);
181 }
182
183 String& String::insert(int i, const char* s)
184 {
185     if( (0 <= i) && (i <= m_length) )
186     {
187         if( ( s != NULL) && ( s[0] != ‘\0‘ ) )
188         {
189             int len = strlen(s);
190             char* str = reinterpret_cast<char*>(malloc(m_length + len + 1));
191
192             if( str != NULL )
193             {
194                 strncpy(str, m_str, i);
195                 strncpy(str + i, s, len);
196                 strncpy(str + i + len, m_str + i, m_length - i);
197
198                 str[m_length + len] = ‘\0‘;
199
200                 free(m_str);
201
202                 m_str = str;
203                 m_length = m_length + len;
204             }
205             else
206             {
207                 THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create str object...");
208             }
209         }
210     }
211     else
212     {
213         THROW_EXCEPTION(IndexOutOfBoundsException, "parameter i is invalid...");
214     }
215
216     return *this;
217 }
218
219 String& String::insert(int i, const String& s)
220 {
221     return insert(i, s.m_str);
222 }
223
224 String& String::trim()
225 {
226     int b = 0;
227     int e = m_length - 1;
228
229     while( m_str[b] == ‘ ‘)b++;
230     while( m_str[e] == ‘ ‘)e--;
231
232     if( b == 0 )
233     {
234         m_str[e + 1] = ‘\0‘;
235
236         m_length = e + 1;
237     }
238     else
239     {
240         for(int i = 0,j = b; j <= e; i++, j++)
241         {
242             m_str[i] = m_str[j];
243         }
244
245         m_str[e - b + 1] = ‘\0‘;
246         m_length = e - b + 1;
247     }
248
249     return *this;
250 }
251
252 int String::indexOf(const char* s) const
253 {
254     return kmp(m_str, s ? s : "");
255 }
256
257 int String::indexOf(const String& s) const
258 {
259     return kmp(m_str, s.m_str);
260 }
261
262 String& String::remove(int i, int len)
263 {
264     if( (0 <= i) && (i < m_length) )
265     {
266         int n = i;
267         int m = i + len;
268
269         while( (n < m) && (m < m_length) )
270         {
271             m_str[n++] = m_str[m++];
272         }
273
274         m_str[n] = ‘\0‘;
275         m_length = n;
276     }
277
278     return *this;
279 }
280
281 String& String::remove(const char* s)
282 {
283     return remove(indexOf(s), s ? strlen(s) : 0);
284 }
285
286 String& String::remove(const String& s)
287 {
288     return remove(indexOf(s), s.length());
289 }
290
291 String& String::replace(const char* t, const char* s)
292 {
293     int index = indexOf(t);
294
295     if( index >= 0 )
296     {
297         remove(t);
298         insert(index, s);
299     }
300
301     return *this;
302 }
303
304 String& String::replace(const String& t, const char* s)
305 {
306     return replace(t.m_str, s);
307 }
308
309 String& String::replace(const char* t, const String& s)
310 {
311     return replace(t, s.m_str);
312 }
313
314 String& String::replace(const String& t, const String& s)
315 {
316     return replace(t.m_str, s.m_str);
317 }
318
319 String String::sub(int i, int len) const
320 {
321     String ret;
322
323     if( (0 <= i) && (i<m_length) )
324     {
325         if( len < 0 ) len = 0;
326         if(len + i > m_length) len = m_length - i;
327
328         char* str = reinterpret_cast<char*>(malloc(len + 1));
329
330         strncpy(str, m_str + i, len);
331
332         str[len] = ‘\0‘;
333
334         ret = str;
335     }
336     else
337     {
338         THROW_EXCEPTION(IndexOutOfBoundsException, "parameter i is invalid...");
339     }
340
341     return ret;
342 }
343
344 char& String::operator [] (int i)
345 {
346     if( (0 <= i) && (i < m_length) )
347     {
348         return m_str[i];
349     }
350     else
351     {
352         THROW_EXCEPTION(IndexOutOfBoundsException, "parameter i is invalid ...");
353     }
354 }
355
356 char String::operator [] (int i) const
357 {
358     return (const_cast<String&>(*this))[i];
359 }
360
361 bool String::operator == (const String& s) const
362 {
363     return ( strcmp(m_str, s.m_str) == 0 );
364 }
365
366 bool String::operator == (const char* s) const
367 {
368     return ( strcmp(m_str, s ? s : "") == 0 );
369 }
370
371 bool String::operator != (const String& s) const
372 {
373     return !(*this == s);
374 }
375
376 bool String::operator != (const char* s) const
377 {
378     return !(*this == s);
379 }
380
381 bool String::operator > (const String& s) const
382 {
383     return (strcmp(m_str, s.m_str) > 0);
384 }
385
386 bool String::operator > (const char* s) const
387 {
388     return (strcmp(m_str, s ? s : "") > 0);
389 }
390
391 bool String::operator < (const String& s) const
392 {
393     return (strcmp(m_str, s.m_str) < 0);
394 }
395
396 bool String::operator < (const char* s) const
397 {
398     return (strcmp(m_str, s ? s : "") < 0);
399 }
400
401 bool String::operator >= (const String& s) const
402 {
403     return (strcmp(m_str, s.m_str) >= 0);
404 }
405
406 bool String::operator >= (const char* s) const
407 {
408     return (strcmp(m_str, s ? s : "") >= 0);
409 }
410
411 bool String::operator <= (const String& s) const
412 {
413     return (strcmp(m_str, s.m_str) <= 0);
414 }
415
416 bool String::operator <= (const char* s) const
417 {
418     return (strcmp(m_str, s ? s : "") <= 0);
419 }
420
421 String String::operator + (const String& s) const
422 {
423     return (*this + s.m_str);
424 }
425
426 String String::operator + (const char* s) const
427 {
428     String ret;
429
430     int len = m_length + strlen(s ? s : "");
431
432     char* str = reinterpret_cast<char*>(malloc(len + 1));
433
434     if( str )
435     {
436         strcpy(str, m_str);
437         strcat(str, s ? s : "");
438
439         free(ret.m_str);
440
441         ret.m_str = str;
442         ret.m_length = len;
443     }
444     else
445     {
446         THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create str object...");
447     }
448
449     return ret;
450 }
451
452 String& String::operator += (const String& s)
453 {
454     return (*this = *this + s.m_str);
455 }
456
457 String& String::operator += (const char* s)
458 {
459     return (*this = *this + s);
460 }
461
462 String String::operator - (const char* s) const
463 {
464     return String(*this).remove(s);
465 }
466
467 String String::operator - (const String& s) const
468 {
469     return String(*this).remove(s);
470 }
471
472 String& String::operator -= (const char* s)
473 {
474     return remove(s);
475 }
476
477 String& String::operator -= (const String& s)
478 {
479     return remove(s);
480 }
481
482 String& String::operator = (const String& s)
483 {
484     return (*this = s.m_str);
485 }
486
487 String& String::operator = (const char* s)
488 {
489     if( m_str != s )
490     {
491         char* str = strdup(s ? s: "");
492
493         if( str )
494         {
495             free(m_str);
496
497             m_str = str;
498             m_length = strlen(m_str);
499         }
500         else
501         {
502             THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create str object...");
503         }
504     }
505
506     return *this;
507 }
508
509 String& String::operator = (char c)
510 {
511     char s[] = {c, ‘\0‘};
512
513     return (*this = s);
514 }
515
516 String::~String()
517 {
518     free(m_str);
519 }
520
521 }

小结:

原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9672250.html

时间: 2024-09-30 15:37:27

第四十二课 KMP算法的应用的相关文章

NeHe OpenGL教程 第四十二课:多重视口

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第四十二课:多重视口 多重视口 画中画效果,很酷吧.使用视口它变得很简单,但渲染四次可会大大降低你的显示速度哦:) 欢迎来到充满趣味的另一课.这次我将向你展示怎样在单个窗口内显示多个视口.这些视口在窗口模式下能正确的调整大小.其中有

JAVA学习第四十二课 — 泛型(二)—泛型接口&amp;&amp;通配符应用

一.泛型接口 interface Inter<T>{ public void show(T t); } class InterImple implements Inter<String>{//知道是字符串类型 public void show(String str){ System.out.println("show "+str); } } class InterImple_2<Q> implements Inter<Q>{//不知道是什

第四十二课:基于CSS的动画引擎

由于低版本浏览器不支持css3 animation,因此我们需要根据浏览器来选择不同的动画引擎.如果浏览器支持css3 animation,那么就使用此动画引擎,如果不支持,就使用javascript的动画引擎. 首先,我们看一下判定条件,方便切换.前面说过,浏览器把所有事件类型的构造器放在window上,只不过不可遍历.我们用Object.getOwnPropertyNames(window),可以得到window对象中的所有属性,然后再filter一下,就能得到所有的事件构造器了.最后,我们

AGG第四十二课 Blitting an image over another with transparency

问题: I've managed to blit a loaded image onto another through the method "copy_from(...)" of renderer_base. I'd like to know how can i blit the same image and also specifying a color that will NOT overwrite the pixels of the destination image ( a

NeHe OpenGL教程 第二十二课:凹凸映射

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第二十二课:凹凸映射 凹凸映射,多重纹理扩展: 这是一课高级教程,请确信你对基本知识已经非常了解了.这一课是基于第六课的代码的,它将建立一个非常酷的立体纹理效果. 这一课由Jens Schneider所写,它基本上是由第6课改写而来

【C++探索之旅】第一部分第十二课:指针一出,谁与争锋

内容简介 1.第一部分第十二课:指针一出,谁与争锋 2.第一部分第十三课预告:第一部分小测验 指针一出,谁与争锋 上一课<[C++探索之旅]第一部分第十一课:小练习,猜单词>中,我们用一个小游戏来总结了之前几课学习的知识点. 现在,终于来到第一部分的最后一个知识点了,也是C++的基础部分的最后一个讲题.之后进入第二部分,就会开始面向对象之旅.因此,这一课也注定不平凡.系好安全带吧,因为马力要加足了! 指针这个C系语言的难点(著名的C语言里也有指针),令无数英雄"尽折腰",也

程序员的奋斗史(四十二)——大学断代史(六)——我与图书馆

文/温国兵 作为一个爱读书之人,图书馆简直是人间天堂.反之,不过地狱. 读书的好处在于,可以穿越古今中外,超越时间和空间的界限,到达你想到达的地方.你可以回到唐朝和诗仙酌酒言欢,可以回到战国和庄子高谈庄周梦蝶.鲲鹏之硕,可以回到18世纪的法国聆听哲人卢梭的教导,可以回到19世纪的德国瞻仰尼采的智慧,可以回到20世纪的中国感受王小波的特立独行,可以回到春秋时期领略老子的道,可以回到20世纪感受徐志摩的唯美诗歌--书中自有黄金屋,书中自有颜如玉,从书中可以获取到广阔的精神食粮,指引着我们前进,教导我

数据结构(十二)——排序算法

数据结构(十二)--排序算法 一.排序简介 1.排序的一般定义 排序是计算机中经常进行的操作,目的在于将一组无序的数据元素调整为有序的数据元素.序列:1,20,45,5,2,12排序后:1,2,5,12,20,45 2.排序的数学定义 3.排序的稳定性 如果序列中的两个元素R[i].R[j],关键字分别为K[i].K[j],并且在排序之前R[i]排在R[j]前面,如果排序操作后,元素R[i]仍然排在R[j]前面,则排序方法是稳定的:否则排序是不稳定的. 4.排序实现的关键 比较:任意两个数据元素

第四十二章

第四十二章1 道生“肾” 道生一,一生二,二生三,三生万物. 道生出混沌之气,混沌之气分出阴阳,阴阳又交汇出新的物质,从而生出万物. 道在我们身体内体现为“肾精”,要保护好.各位朋友大家好,今天我们接着来聊<道德经>.我们来看看老子带给我们什么样新的人生启发了,每天启发一点,天天进步.今天我们开始学习第四十二章,非常开心.因为我们<道德经>已经学习到一半的位置了,因为整个八十一章,我们学习到第四十二章了,过了一半了,这时间也是飞快的.我之前预计3年,我估计现在2年差不多讲完了.因为