这一章学习之后,我想对串这个部分写一下我的总结体会。

  串也有顺序和链式两种存储结构,但大多采用顺序存储结构比较方便。字符串定义可以用字符数组比如:char c[10];也可以用C++中定义一个字符串string a;这就需要根据具体场景来选择合适方便操作的方法。还有空串和空格串是不同的,空串字符长度为0(符号‘),空格串包含一个或多个空格。这一章学习了两个串的模式匹配算法,特别是KMP算法,从中受益匪浅。

一、串

1、BF(Brute-Force)算法

  这个模式匹配算法简单直观,被人们称为暴力算法。它就是将模式串跟主串从开头一个一个比较,如果匹配失败,又从模式串第二个字符一次比较,以此类推,逻辑思维不高,所以简单,容易理解,现在用途还很大。

       i 0 1 2 3 4
主串 a b c a b
模式串j(第1次比较) c a b    
          (第2次比较)   c a b  
          (第3次比较)     c a b

这里我是用字符串下标,从0开始,可以看出每次比较模式串都从j=0开始,而i就是上次初始比较的下一个就是i=i-j+1,比如上面的第一次比较后i=0,j=0;下一次i=0-0+1,即从i=1进行匹配。

现在以题目为例,写一下我的解题过程。

7-1 串的模式匹配 

  给定一个主串S(长度<=10^6)和一个模式T(长度<=10^5),要求在主串S中找出与模式T相匹配的子串,返回相匹配的子串中的第一个字符在主串S中出现的位置。

  输入格式:  输入有两行: 第一行是主串S; 第二行是模式T.

  输出格式:     输出相匹配的子串中的第一个字符在主串S中出现的位置。若匹配失败,输出0.

输入样例:

在这里给出一组输入。例如:

aaaaaba
ba

输出样例:

在这里给出相应的输出。例如:6

int BF(string A,string B)//这里算法是从下标为0开始,所以跟书里有点不同
{
int i=,j=;
while(i<A.length()&&j<B.length())
{
if(A[i]==B[j])
{
++i;++j;
}
else
{
i=i-j+;j=;//根据上面分析,下标后退进行比较
}
}
if(j>=B.length()) return i-j+; //返回匹配成功第一个位置
return ;
}

我感觉用下标比较容易操作,只需要改一下相应的位置,然后直接用C++定义字符串string,再输入字符串,相对也比较简洁。

主函数如下:

int main()
{
string a,b;
getline(cin,a);//输入一个串之后回车就可以输入下一个串
getline(cin,b);
//int num=BF(a,b);
//int num=KMP(a,b);这里两个选一个,下面KMP算法的主函数一样
cout<<num;
return ;
}

这道题用BF算法可以简单就解决了,那为啥还要有KMP算法呢?

  一般情况下,BF算法时间复杂度为O(m*n),数据量不大时候,执行时间近似为O(m+n),但如果是庞大数据,那它的效率就很低了,我们老师专门设了一个测试点主串长度100万,模式长度10万,而且是那种主串为aaaaaaaa...,模式串是ba......。所以,从第一个字符比较一直不匹配,而模式串一直回溯到j=0,这样工作量超大,所以上面BF算法提交之后在这个测试点是运行超时的。

这样,才有优化算法KMP,第一次看的时候一脸懵,无法理解三个大牛的逻辑思维。所以我搜索了几篇博客认真学习,试图融入大牛的思维世界。

(链接:https://blog.csdn.net/henuyx/article/details/44653799https://www.cnblogs.com/tangzhengyue/p/4315393.html

2、KMP算法

这种改进算法是由D.E.Knuth、J.H.Morris、V.R.Pratt三位大牛同时设计实现的。下面我就捋一下我入门的思路方法。

  KMP最让人难以理解就是它的next数组是如何得到的,开始我觉得很神奇,next数组居然实现了字符匹配的“跳转”。举个例子,看看是如何算出next数组的。

模式串  a b a a b c a c


下标 j  0 1 2 3 4 5 6 7


next[j] -1 0 0 1 1 2 0 1

先算一下每个字符的最长相等前后缀吧

  前缀 后缀 最长相等前后缀
a 0
ab a b 0
aba a,ab a,ba 1
abaa a,ab,aba a,aa,baa 1
abaab a,ab,aba,abaa b,ab,aab,baab 2
abaabc a,ab,aba,abaa,abaab c,bc,abc,aabc,baabc, 0
abaabca a,ab,aba,abaa.abaab,abaabc a,ca,bca,abca,aabca,baabca 1
abaabcac a,ab,aba,abaa,abaab,abaabc,abaabca c,ac,cac,bcac,abcac,aabcac,baabcac 0

经过观察,每个字符对应next数组的值为其前面的字符的最长相等前后缀,然后因为时按下标比较,将next[0]=-1;所以现在给出任意一个模式串,都可以很快确定它的next数组值。如:a b c d a b d, next[j]={-1,0,0,0,0,1,2}。现在就上计算next值的算法:

int* getnext(string T)  //定义指针函数getnext(),求模式串T的next函数值并放入next数组
{
int* next = new int[T.length()]; //动态申请模式串T存储空间
int Tl = T.length();
int i = ; // T的下标
int j = -; //因为是按下标比较,所以 j = -1,next[0] = -1;
next[] = -;
while(i<Tl)//T串未比较到串尾
{
if(j==-||T[i]==T[j])//若字符匹配,或者j==-1,则进行下一个字符比较,并求出T[i]字符对应的next值
{ //T[i]是后缀,T[j]是前缀
++i;++j;next[i]=j;
}
else j=next[j];//若字符不匹配,求出字符对应的next值
}
return next;//因为是指针函数 ,所以返回next数组首地址 }

刚开始,根据书里的代码实现不了将next传到KMP函数体里面,查了相关资料,可以通过指针函数将数组传过去,其实是返回数组首地址。

  KMP算法函数:

int KMP(string S,string T)//KMP算法
{
int i=,j=;
int sl=S.length();
int tl=T.length();
int *next=getnext(T);//用next指针接受指针函数传来的数组地址 while(i<sl&&j<tl)
{
if(j==-||S[i]==T[j])//如果j = -1,或者当前字符匹配成功(即S[i] == P[j])
{
++i;++j;
}
else
{
j=next[j];//next[j]即为j所对应的next值
}
}
if(j>=tl) return i-j+;//匹配成功,返回第一次匹配位置
else return ;//匹配失败,返回0
}

这道题我从理解到完成用了差不多1天时间,大部分时间花费在理解算法上面,特别是“跳转”的next数组,感觉既神奇又有趣。而PTA的这道题经过几次debug,主要是细节错误导致开始运行结果错误。就这样,要通过最后一个测试点然后学到了KMP算法思想,还是挺好的。

二、数组

主要学习是特殊矩阵的压缩存储,节省空间,放入新的数组,还有稀疏矩阵,用三元组表来表示,而十字链表就比较难了。三元组定义:

typedef struct{
int i,j,value; //行下标i,列下标j,值value
}node;//三元组 typedef struct{
int m,n,nzero;//矩阵行数m,矩阵列数n,非零个数nzero
node a[];//三元组数组
}Matrix;//三元组表

PTA上面用这个方法就很简单解决

现在存在的问题就是,写代码能力不高,思路虽然比较清晰,但是再转化为代码时候需要花较多时间,上次小测也是这样,因为写代码量不够,最后做题时间不够,最后一道简单的题目没来得及做,所以,以后需要花时间读写代码,这样才能做得更好。谢谢您的阅读!

第4章学习小结_串(BF&KMP算法)、数组(三元组)的更多相关文章

  1. 数据结构学习之字符串匹配算法(BF||KMP)

    数据结构学习之字符串匹配算法(BF||KMP) 0x1 实验目的 ​ 通过实验深入了解字符串常用的匹配算法(BF暴力匹配.KMP.优化KMP算法)思想. 0x2 实验要求 ​ 编写出BF暴力匹配.KM ...

  2. 数据结构之BF算法,kmp算法,三元组,十字链表总结

    在这一章中,老师教了我们四种数据结构:BF算法,kmp算法,三元组和十字链表:还给我们讲了2019年团体天体赛中T1-8的AI题 1.对于BF和kmp算法,老师除了在课堂上讲解算法的主要核心思想外,还 ...

  3. hdu 3336:Count the string(数据结构,串,KMP算法)

    Count the string Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  4. 串的两种模式匹配方式(BF/KMP算法)

    前言 串,又称作字符串,它是由0个或者多个字符所组成的有限序列,串同样可以采用顺序存储和链式存储两种方式进行存储,在主串中查找定位子串问题(模式匹配)是串中最重要的操作之一,而不同的算法实现有着不同的 ...

  5. 数据结构与算法JavaScript (五) 串(经典KMP算法)

    KMP算法和BM算法 KMP是前缀匹配和BM后缀匹配的经典算法,看得出来前缀匹配和后缀匹配的区别就仅仅在于比较的顺序不同 前缀匹配是指:模式串和母串的比较从左到右,模式串的移动也是从 左到右 后缀匹配 ...

  6. 常用算法3 - 字符串查找/模式匹配算法(BF & KMP算法)

    相信我们都有在linux下查找文本内容的经历,比如当我们使用vim查找文本文件中的某个字或者某段话时,Linux很快做出反应并给出相应结果,特别方便快捷! 那么,我们有木有想过linux是如何在浩如烟 ...

  7. 第3章:LeetCode--算法:strStr KMP算法

    https://leetcode.com/problems/implement-strstr/  28. Implement strStr() 暴力算法: int ViolentMatch(char* ...

  8. 串和KMP算法

    一.串 串是由零个或多个字符串组成的有限序列 (一).串的定义 定长顺序存储 特点:每个串变量分配一个固定长度的存储区,即定长数组 定义: #define MAXLEN 255 typedef str ...

  9. 20181117-python第二章学习小结-part2

    浮点型补充: 有限小数与无限循环小数,不包括无理数! 小数点后面的数据运算太复杂,精确度不及整数! 尽量使用科学计数表示小数 列表学习(语法) 创建:[] list = []  #创建空表 list ...

随机推荐

  1. LeetCode算法题-1-bit and 2-bit Characters(Java实现)

    这是悦乐书的第302次更新,第321篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第170题(顺位题号是717).有两个特殊字符,第一个字符可以用一个比特0表示,第二个字 ...

  2. linux使用Nginx搭建静态资源服务器

    最近公司需要做一个宣传片播放  视频有点大 好几百M 就想到使用Nginx来代理静态资源,在过程中出现了一些问题,比如端口没开.访问是403等,没有成功,后面慢慢查找问题,才发现大部分博客资料的都不全 ...

  3. Web框架本质及第一个Django实例

    Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web框架了. 半成品自定义web框架 impor ...

  4. flask-cache报错No module named 'flask.ext;解决方案

    找到flask-cache包中的jinja2ext.py,将from flask.ext.cache import make_template_fragment_key改为from flask_cac ...

  5. RequestMapper

    @RequestMapping(value = "/v1/getAllUrl", method = RequestMethod.POST) public Object getAll ...

  6. IdentityServer4实战 - 与API单项目整合

    一.前言 我们在实际使用 IdentityServer4 的时候,可能会在使用 IdentityServer4 项目添加一些API,比如 找回密码.用户注册.修改用户资料等,这些API与Identit ...

  7. TypeScript 之类型判断

    在使用 Angular 做项目的时候,对 TypeScript 的类型判断不太熟练,为了方便查找,特意对 TypeScript 的类型判断做了简单梳理.文章只是 TS 官网的内容摘要,没有高深的知识, ...

  8. Kubernetes 网络排错指南

    本文介绍各种常见的网络问题以及排错方法,包括 Pod 访问异常.Service 访问异常以及网络安全策略异常等. 说到 Kubernetes 的网络,其实无非就是以下三种情况之一 Pod 访问容器外部 ...

  9. subgradients

    目录 定义 上镜图解释 次梯度的存在性 性质 极值 非负数乘 \(\alpha f(x)\) 和,积分,期望 仿射变换 仿梯度 混合函数 应用 Pointwise maximum 上确界 suprem ...

  10. 前端可视化项目流程,涉及three.js(webGL),3DMax技术,持续更新

    最近在做一个可视化展示的项目,记录一下流程: 建模,模型来源,可以参考沙盘展示类项目,自己建模或者拼装其他源模型(本人以前是3D建模师,可以应付一些简单的场景) 有效模型导入到web端,这里采用的ob ...