串的模式匹配
2016-05-07 18:40
302 查看
问题描述:
对于两个字符串A,B。请设计一个高效算法,找到B在A中第一次出现的起始位置。若B未在A中出现,则返回-1。
给定两个字符串A和B,及它们的长度lena和lenb,请返回题目所求的答案。
测试样例:
"acbc",4,"bc",2
返回:2
思路:1,该类型题目的一般思路是暴力求解,采用两层循环,我们会从A[0] 跟B[0] 匹配,如果相等则匹配下一个字符,直到出现不相等的情况,此时我们会简单的丢弃前面的匹配信息,然后从A[1] 跟 B[0]匹配,循环进行,直到主串结束,或者出现匹配的情况。这种简单的丢弃前面的匹配信息,造成了极大的浪费和低下的匹配效率。时间复杂度是o(nlogn)。
(暴力方法)AC代码如下:
2,采用KMP算法,可以使时间复杂度降低到o(m+n)。
网上关于KMP算法的介绍有很多,我在这里简单介绍一下思路:
我们需要一个辅助数组next[],用于存放我们事先计算的模式串的内部匹配信息,在匹配失败时最大的移动模式串,以减少匹配次数。next数组的长度和模式串的长度是一样的,next在位置index中存放的内容是模式串的index位置之前的整个子串的最长的相同的前缀和后缀的长度。右移的距离是如此计算的:在已经匹配的模式串子串中,找出最长的相同的前缀和后缀,然后移动使它们重叠。·
模式匹配过程中,如果主串和模式串的对应字符相等,则主串下标和模式串下标均加1,如果主串和模式串的字符不相等,则判断模式串的下标是否为0,若为0,则是主串的下标加1,继续匹配,若不为0,则使模式串的下标等于next数组中对应位置的值,继续匹配,知道主串下标等于主串的长度或者模式串的下标值等于模式串的长度。这时模式串的下标值若为模式串的长度,则返回主串的下标值减去模式串的长度,否则返回-1。
(KMP算法)AC代码:
对于两个字符串A,B。请设计一个高效算法,找到B在A中第一次出现的起始位置。若B未在A中出现,则返回-1。
给定两个字符串A和B,及它们的长度lena和lenb,请返回题目所求的答案。
测试样例:
"acbc",4,"bc",2
返回:2
思路:1,该类型题目的一般思路是暴力求解,采用两层循环,我们会从A[0] 跟B[0] 匹配,如果相等则匹配下一个字符,直到出现不相等的情况,此时我们会简单的丢弃前面的匹配信息,然后从A[1] 跟 B[0]匹配,循环进行,直到主串结束,或者出现匹配的情况。这种简单的丢弃前面的匹配信息,造成了极大的浪费和低下的匹配效率。时间复杂度是o(nlogn)。
(暴力方法)AC代码如下:
class StringPattern { public: int findAppearance(string A, int lena, string B, int lenb) { // write code here int i,j,k; for(i=0;i<lena;i++){ k=i; for(j=0;j<lenb;j++,k++) if(A[k]!=B[j]) break; if(j==lenb) return i; } return -1; } };
2,采用KMP算法,可以使时间复杂度降低到o(m+n)。
网上关于KMP算法的介绍有很多,我在这里简单介绍一下思路:
我们需要一个辅助数组next[],用于存放我们事先计算的模式串的内部匹配信息,在匹配失败时最大的移动模式串,以减少匹配次数。next数组的长度和模式串的长度是一样的,next在位置index中存放的内容是模式串的index位置之前的整个子串的最长的相同的前缀和后缀的长度。右移的距离是如此计算的:在已经匹配的模式串子串中,找出最长的相同的前缀和后缀,然后移动使它们重叠。·
模式匹配过程中,如果主串和模式串的对应字符相等,则主串下标和模式串下标均加1,如果主串和模式串的字符不相等,则判断模式串的下标是否为0,若为0,则是主串的下标加1,继续匹配,若不为0,则使模式串的下标等于next数组中对应位置的值,继续匹配,知道主串下标等于主串的长度或者模式串的下标值等于模式串的长度。这时模式串的下标值若为模式串的长度,则返回主串的下标值减去模式串的长度,否则返回-1。
(KMP算法)AC代码:
class StringPattern { public: int findAppearance(string A, int lena, string B, int lenb) { // write code here if(lenb==0) return -1; int next[lenb]; next[0]=-1; next[1]=0; int pos=2; int cn=0; while(pos<lenb){ //计算next数组 if(B[pos-1]==B[cn]) next[pos++]=++cn; else if(cn>0) cn=next[cn]; else next[pos++]=0; } int j=0,k=0; while(j<lenb && k<lena){ //模式匹配过程 if(A[k]!=B[j]){ if(j==0) k++; else j=next[j]; } else{ j++; k++; } } if(j>=lenb) return k-lenb; return -1; } };
相关文章推荐
- 关于Android的不同分辨率图片适配
- Execution failed for task ':app:mergeDebugResources
- Emacs 常用配置
- 深度学习——Xavier初始化方法
- SQL SERVER透视转换(行旋转列)
- DOM扩展学习笔记
- 牧场物语
- SpringMVC异常统一处理
- Linux:信号(上)
- redis集群搭建之二~使用redis-trib.rb方法
- C++11六大函数(构造函数,移动构造函数,移动赋值操作符,复制构造函数,赋值操作符,析构函数)
- LeetCode---Palindrome Number解题分析
- 块设备驱动程序(Linux设备驱动程序)
- iOS 星星评分评分控件
- Unity两个物体发生碰撞的条件
- Linux中执行shell脚本的4种方法总结
- Search for a Range
- 蛇形填数
- matlab中cell的用法
- 探索博客园的“打赏”模式