千家信息网

KMP 算法的应用(二十七)

发表于:2024-10-24 作者:千家信息网编辑
千家信息网最后更新 2024年10月24日,我们在上节博客中讲到了 KMP 算法的具体实现,那么我们本节就来看看 KMP 算法的应用。问题:如何在目标字符串中查找是否存在指定的子串?我们来看看字符串类中的新功能,如下图所示1、子串查找(KMP
千家信息网最后更新 2024年10月24日KMP 算法的应用(二十七)

我们在上节博客中讲到了 KMP 算法的具体实现,那么我们本节就来看看 KMP 算法的应用。问题:如何在目标字符串中查找是否存在指定的子串

我们来看看字符串类中的新功能,如下图所示

1、子串查找(KMP 算法的直接应用)

int indexOf(const char* s) const;

int indexOf(const String& s) const;

我们来看看具体源码的实现,如下

int String::indexOf(const char* s) const{    return kmp(m_str, s ? s : "");}int String::indexOf(const String& s) const{    return kmp(m_str, s.m_str);}

直接利用我们上节博客实现的 kmp 函数就能实现 indexOf 函数,我们来看看效果

#include #include #include "DTString.h"using namespace std;using namespace DTLib;int main(){    String s = "ababax";    cout << s.indexOf("bax") << endl;    return 0;}

编译运行结果如下

我们看到返回的位置为下标为 3 处,也就是 s[3] 处。

2、在字符串中将指定的子串删除

String& remove(int i, int len);

String& remove(const char* s);

String& remove(const String& s);

根据 KMP 在目标字符串中查找子串的位置,再通过子串位置和子串长度进行删除。具体源码实现如下

String& String::remove(int i, int len){    if( (0 <= i) && (i < m_length) )    {        int n = i;        int m = i + len;        while( (n < m) && (m < m_length) )        {            m_str[n++] = m_str[m++];        }        m_str[n] = '\0';        m_length = n;    }    return *this;}String& String::remove(const char* s){    return remove(indexOf(s), s ? strlen(s) : 0);}String& String::remove(const String& s){    return remove(indexOf(s), s.length());}

我们来写个测试代码进行测试,如下

#include #include #include "DTString.h"using namespace std;using namespace DTLib;int main(){    String s = "ababax";    cout << s.remove("bab").str() << endl;    return 0;}

我们来看看结果是不是 aax,如下

3、字符串的减法操作定义(operator -)

使用 remove 实现字符串间的减法操作,必须得保证字符串自身不被修改,返回产生的新串。最后效果如下

String operator - (const String& s) const;

String operator - (const char* s) const;

String& operator -= (const String& s);

String& operator -= (const char* s);

利用原有的 + 操作符进行改装即可,源码实现如下

String String::operator - (const String& s) const{    return String(*this).remove(s);}String String::operator - (const char* s) const{    return String(*this).remove(s);}String& String::operator -= (const String& s){    return remove(s);}String& String::operator -= (const char* s){    return remove(s);}

我们来测试下,测试代码如下

#include #include #include "DTString.h"using namespace std;using namespace DTLib;int main(){    String s = "ababax";    String s1 = s - "bax";    cout << s.str() << endl;    cout << s1.str() << endl;    s -= s;    cout << "[" << s.str() << "]" << endl;    return 0;}

我们来看看运行结果,s1 = "aba", 最后的 s 应该为空,我们来看看结果

我们看到结果正如我们所分析的那样。

4、字符串中的子串替换

String& replace(const char* t, const char* s);

String& replace(const String& t, const char* s);

String& replace(const char* t, const String& s);

String& replace(const String& t, const String& s);

我们来看看具体源码的实现

String& String::replace(const char* t, const char* s){    int index = indexOf(t);    if( index > 0 )    {        remove(t);        insert(index, s);    }    return *this;}String& String::replace(const String& t, const char* s){    return replace(t.m_str, s);}String& String::replace(const char* t, const String& s){    return replace(t, s.m_str);}String& String::replace(const String& t, const String& s){    return replace(t.m_str, s.m_str);}

我们来写个测试代码进行测试,代码如下

#include #include #include "DTString.h"using namespace std;using namespace DTLib;int main(){    String s = "ababax";    s.replace("baba", "xyz");    cout << s.str() << endl;    return 0;}

我们来看看最后的结果是不是 axyzx,运行结果如下

5、从字符串中创建子串

String sub(int i, int len) const;

以 i 为起点提取长度为 len 的子串,子串提取保证不会改变字符串本身的状态。如下

具体源码实现如下

String String::sub(int i, int len) const{    String ret;    if( (0 <= i) && (i < m_length) )    {        if( len < 0 ) len = 0;        if( len > m_length ) len = m_length - i;        char* str = static_cast(malloc(len + 1));        strncpy(str, m_str + i, len);        str[len] = '\0';        ret = str;    }    else    {        THROW_EXCEPTION(IndexOutOfBoundsException, "Parameter i is invalid ...");    }    return ret;}

我们来写个测试代码进行测试,测试代码如下

#include #include #include "DTString.h"using namespace std;using namespace DTLib;int main(){    String s = "ababax";    String s1 = s.sub(3, 10);    String s2 = s.sub(2, 3);    cout << s.str() << endl;    cout << s1.str() << endl;    cout << s2.str() << endl;    return 0;}

最后的结果应该是 s = "ababax" ; s1 = "bax" ; s3 = "aba" ; 运行结果如下

现在我们的字符串类已经实现的有点规模了。通过今天对字符串类的学习,总结如下:1、字符串类是工程开发中必不可少的组件;2、字符串中应该包含常用的字符串操作函数,a> 增:insert, operator + , ...; b> 删:remove,operator -,...; c> 查:indexOf,...; d> 改:replace,...

字符 字符串 结果 测试 代码 源码 运行 算法 位置 函数 应用 减法 博客 效果 目标 长度 保证 下标 中将 也就是 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 局域网中的数据库是干什么的 校园网络安全系统 网络安全 政策法规 一台服务器的同时在线人数 服务器 香港 数据库设计大学课程安排系统 网易服务器和签到卡是怎么整的 服务器成员怎么调管理员 网络安全建设的思路与对策 软件开发中pm组是什么意思 导出数据库报错怎么办 交行网络安全宣传 osee网络安全 黑据点找出主数据库服务器 怎么根据实体类设计数据库表 虹口区智能软件开发收费 软件开发应遵循怎样的工作流 游戏服务器 安全设置 潜江市友乐网络技术有限责任公司 电子邮件服务器警报 手机设置微博清除数据库 阿里云服务器 lamp 长春亿达华信5g网络技术 数据库连接用户怎么测试连接 手游阴阳师百闻牌连接不上服务器 一个数据库的外模式可能有多个 数据库 性能优化 央企网络安全大赛获奖名单 千喜网络技术公司 数据库更改后显示不能保存
0