using namespace std;
#include <iostream>
#include<string> //自定义字符串存储结构String(包括char数组、length长度)
#define maxlen 20
typedef struct {
char ch[maxlen];
int length;
}String; //初始化s
void strInit(String& s) {
s.length = 0;
s.ch[0] = s.length; //ch[0]空着用来存长度,初始化为0
} //s判空
bool strEmpty(String s) {
if (s.length == 0) //如果长度为0代表空串
return true;
else
return false;
} //获得s长度
int strLength(String s) {
cout << "长度打印:" << s.length << endl;;
return s.length; //或者s.ch[0]
} //将string字符串赋值到s数据结构中用char数组保存
String strAssign(String &s, string t) {
int i = 1; //从1开始存字符,0空着用来存长度
s.length =0;
cout << "字符串打印:";
for (int j = 0; j < t.length(); j++) {
s.ch[i] = t[j];
cout << s.ch[i] << " ";
s.length++;
i++;
}
s.ch[0] = s.length; //0空着用来存长度
cout << endl;
return s;
} /////////上面都是一些基础函数,下面开始KMP算法/////////////////////////////////////////////
//step1:求出子串的next[j]值【普通版】
void get_next(String s, int next[]) {
int j = 1, k = 0;
next[1] = 0; //next[1]值必须填0
while(j<s.length){
if (s.ch[j] == s.ch[k] || k == 0) {
j++;
k++;
next[j] = k;
}
else
k = next[k];
}
//打印看看
cout <<"打印next[i]为: ";
for (int i = 1; i <=s.length; i++)
cout << next[i] << " ";
cout << endl;
} //step1:求出子串的nextval[j]值【改进版,只记录不相同值的索引,避免j的无效回退。2个方法2选1即可】
void get_nextval(String s, int nextval[]) {
int j = 1, k = 0;
nextval[1] = 0; //nextval[1]值必须填0
while (j < s.length) {
if (s.ch[j] == s.ch[k] || k == 0) {
j++;
k++;
if (s.ch[j] != s.ch[k])
nextval[j] = k;
else
nextval[j] = nextval[k];
}
else
k = nextval[k];
}
//打印看看
cout << "打印nextval[i]为: ";
for (int i = 1; i <= s.length; i++)
cout << nextval[i] << " ";
cout << endl;
} //step2:开始主串中匹配子串,并返回第一个元素出现的位置
int index3(String s, String t, int next[]) {
int i = 1, j = 1;
while (i <= s.length && j <= t.length) { //找到最后一个字符为止
if (j == 0||s.ch[i] == t.ch[j]) { //如果字符不相同或者j为0了,i和j同步往后移1位
i++;
j++;
}
else
j = next[j]; //j回退到next[j]位置
}//while结束,s和t至少有一个找到头了
if (j > t.length) {
//打印看看
cout << "index3打印子串为: ";
for (int m = i - t.length; m < i; m++)
cout << s.ch[m] << " ";
cout << endl;
return (i - t.length); //或者i-t.length,返回i最开始的位置
}
else
return 0;
} void main() {
int next[20];
  int nextval[20];
  string sf = "aaaacabcaaaabab";
  string sz = "aaaab"; String ss ,tt;
strInit(ss); //初始化主串
strInit(tt); //初始化子串
strAssign(ss, sf); //把字符串放进数据结构
strAssign(tt, sz); //把字符串放进数据结构
strLength(ss); //获取长度
strLength(tt); //获取长度 get_next(tt, next); //获得子串各个next值
cout << "用next的index3 i下标:" << index3(ss, tt, next) << endl; get_nextval(tt, nextval); //获得子串各个nextval值
cout << "用nextval的index3 i下标:" << index3(ss, tt, nextval) << endl;
}

KMP子串匹配(只能匹配出唯一子串)的更多相关文章

  1. “全栈2019”Java异常第十一章:重写方法时只能抛出父类异常子集

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...

  2. 一个try可以跟进多个catch语句,用于处理不同情况,当一个try只能匹配一个catch

    一个try可以跟进多个catch语句,用于处理不同情况.当一个try只能匹配一个catch. 我们可以写多个catch语句,但是不能将父类型的exception的位置写在子类型的excepiton之前 ...

  3. 为什么HTML中的多个空格或是回车在浏览器上只能显示出一个?

    我们在学习HTML的时候可能书本或是老师会告诉我们一件事,就是在HTML中不管我们在两个文本之间加上多少连续的空格或是回车,到了浏览器里面只能显示出一个来.但是我们从来不知道为什么. 原因很简单,因为 ...

  4. 循环匹配出图片地址(即src属性)

    <script type="text/javascript"> //思路分两步:作者(yanue). //1,匹配出图片img标签(即匹配出所有图片),过滤其他不需要的 ...

  5. 请用正则表达式匹配出QQ号(假设QQ号码为5—10位);

    请用正则表达式匹配出QQ号(假设QQ号码为5—10位): 解答: ^ \d{5,10}$

  6. KMP算法,匹配字符串模板(返回下标)

    //KMP算法,匹配字符串模板 void getNext(int[] next, String t) { int n = next.length; for (int i = 1, j = 0; i & ...

  7. HDU-2087 剪花布条 字符串问题 KMP算法 查匹配子串

    题目链接:https://cn.vjudge.net/problem/HDU-2087 题意 中文题咯 一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案.对于给定的花布条和小饰条, ...

  8. KMP算法——字符匹配

     暴力匹配: 假设现在我们面临这样一个问题:有一个文本串S,和一个模式串P,现在要查找P在S中的位置,怎么查找呢? 如果用暴力匹配的思路,并假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置, ...

  9. 一个简易的kmp教学并给出java实现

    简单介绍一下问题 给定source字符串,找出target字符串出现的首位 例如 source   为“abddabddabc” target 为 “abddabc” 从第一位开始比较 |a b d ...

随机推荐

  1. laya fgui 超简单的UI框架

    FairyGUI 超简单的UI框架 Laya使用fgui的超简单UI框架 使用场景:用于使用fgui进行layaUI开发的程序人员 整个框架分为3个模块,共有4个类: FGUIManager :FGU ...

  2. SpringBoot线程池的创建、@Async配置步骤及注意事项

    最近在做订单模块,用户购买服务类产品之后,需要进行预约,预约成功之后分别给商家和用户发送提醒短信.考虑发短信耗时的情况所以我想用异步的方法去执行,于是就在网上看见了Spring的@Async了. 但是 ...

  3. VisualStudio自动添加注释

    1.VisualStudio  新开页自动添加注释 a 在团队开发或者公司开发中,我们一般都喜欢给自己所创建的类或者接口以及其它模板设置版权说明,但是每个类一个一个的去加又是非常的费劲,所以一般情况下 ...

  4. 6.17考试总结(NOIP模拟8)[星际旅行·砍树·超级树·求和]

    6.17考试总结(NOIP模拟8) 背景 考得不咋样,有一个非常遗憾的地方:最后一题少取膜了,\(100pts->40pts\),改了这么多年的错还是头一回看见以下的情景... T1星际旅行 前 ...

  5. Linux命令大全之挂载命令

    理解:Linux挂载相当于Windows分配盘符 1.查询系统中已挂载的设备 mount 2.设置自动挂载 编辑文件/etc/fstab,把文件写入就可以启动自动挂载了, 注:一般不把光盘写入,如果写 ...

  6. ESCMScript(1)let和const

    1.let命令 基本语法 ES6 新增了let命令,用来声明变量.它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效. { let a = 1 var b = 2 console ...

  7. Task异常捕获的方式

    这节来讲一下如果捕获Task的异常. 当Task运行中出现了异常,正常情况下我们在主线程的Try是捕获不到的,而如果在Task内部写try,出现了异常我们会完全不知道.下面就来介绍几个主线程捕获Tas ...

  8. POJ 1873 The Fortified Forest 凸包 二进制枚举

    n最大15,二进制枚举不会超时.枚举不被砍掉的树,然后求凸包 #include<stdio.h> #include<math.h> #include<algorithm& ...

  9. 安卓手机改造服务器——基本环境配置(CentOS7 arm32)

    安装好CentOS系统之后,我们需要对环境进行一些基本的配置,让Linux更好用 写在前面 注意:本文章是针对arm32的CentOS7进行配置的,其他系统或不同架构不要尝试. 配置yum镜像源 1. ...

  10. [小技巧] google map使用

    在网页中打开 google map 中,可以使用 shift + - 来缩小地图,shift + + 来放大地图.