zoukankan      html  css  js  c++  java
  • 第42课 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, ''};
    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] != '' ) )
    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] = '';
    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] = '';
    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] = '';
    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] = '';
    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] = '';
    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, ''};
    512 
    513     return (*this = s);
    514 }
    515 
    516 String::~String()
    517 {
    518     free(m_str);
    519 }
    520 
    521 }
    复制代码

    小结:

                     

  • 相关阅读:
    Oracle 表空间使用率
    sqlserver 查询主外键索引常用语句
    sqlserver查版本信息
    sqlserver事务日志已满原因分析
    sqlserver创建dblink链接Oracle
    Oracle的DBMS_METADATA.GET_DDL()函数
    Mysql 基于GTID的主从复制(实操)
    Mysql 基于日志点的主从复制(实操)
    修改Linux命令提示符
    MYSQL 二进制安装
  • 原文地址:https://www.cnblogs.com/liuyueyue/p/13521486.html
Copyright © 2011-2022 走看看