KMP模板整理

KMP与扩展KMP;

/*vs 2017/ vs code以外编译器,去掉windows.h头文件和system("pause");*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<Windows.h>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = ; /* KMP */
void Get_Next(char x[], int m, int Next[])
{
/*x[]为模式串P, m为模式串P的长度*/
int i = , j;
j = Next[] = -;
/*以P[0]为终点的子串没有真前缀,有且只有一个假前缀为本身,故Next[0]= -1*/
while (i < m)
{
while (- != j && x[i] != x[j]) j = Next[j];
/*while当P[i]与P[j]不匹配时,
去寻找上一个与P[j]处境相同的位置,即有相同前缀的点Next[j],与P[i]比较*/
Next[++i] = ++j;
/*当P[i]与P[j]处境相似且元素相等时,
那么Next[i+ 1]= j+ 1; 意思是P[i+ 1]与P[j+ 1]的处境相似,即有相同的前缀*/
}
}
int KMP_Count(char x[], int m, char y[], int n, int Next[])
{
/*x[]为模式串P,m为P的长度;y[]为文本串T,n为T的长度*/
int i, j;
i = j = ;
int cnt = ;
while (i < n)
{
while (- != j && y[i] != x[j]) j = Next[j];
/*若T[i]!= P[j];则寻找上一个与P[j]前缀相同的地址Next[j];然后与T[i]比较*/
++i; ++j;
if (j >= m)
{
++cnt;
j = Next[j];
}
}
return cnt;
} /* 扩展KMP */
void Get_e_Next(char x[], int m, int e_Next[])
{
/*x[]为模式串P;m是P的长度;e_Next[i]表示模式串P中,
以P[i]为起点的后缀与模式串P的最长公共前缀的长度*/
e_Next[] = m;
/*字符串s0与自身的最长前缀长度等于自身的长度*/
int j = ;
while (j + < m&& x[j] == x[j + ]) j++;
e_Next[] = j;
/*用while循环寻找以P[1]为起点的后缀与P的最长公共前缀*/
int k = ;
for (int i = ; i < m; i++)
{
/*此时,以P[k]为起点的后缀是最新(近)一次循环查找过与模式串P最长公共前缀的子串*/
int p = k+ e_Next[k] - ;
/*;P[p]是模式串P以P[k]为起点的后缀与P的最大公共前缀的末位元素;
即:P[k, p]= P[0, p- k]; 最大公共前缀的长度为(p- k+ 1)*/
int L = e_Next[i - k];
/*由上面P[k, p]= P[0, p- k]可得,故P[i, p]= P[i- k, p- k];
L= e_Next[i- k]; 即以P[i- k]为起点的后缀有长度为L的前缀与P[0, L- 1]相同,
即由上面的关系可证,P[i]为起点的后缀也与P有一个长度为L的最大公共前缀*/
if (i + L <= p)
{
/*如果i+ L的长度不超过目前已扫描的范围,则e_Next[i]= L;
否则,则要重新扩大处理的范围*/
e_Next[i] = L;
}
else
{
/*若上面判断目前扫描的范围已经不足时,继承之前处理的结果,继续向后处理*/
j = max(, p - i + );
/*j为p- i+ 1,即P[i]之后已经处理过的元素数量;P[i+ j]是其后第一个未处理的元素*/
while (i + j < m&& x[i + j] == x[j]) j++;
/*从P[i+ j]开始,比较P[i]为起点的后缀与P,在两者第j位以后的部分开始比较*/
e_Next[i] = j;
k = i;
/*处理完成后,k更新为i;i+ e_Next[i]- 1是当前处理过的最后一个元素;
当以后的处理要超过这一界线时,要再次处理,然后更新k的值*/
}
}
}
void e_KMP(char x[], int m, char y[], int n, int e_Next[], int extend[])
{
/*x[]是模式串P,m是P的长度,y[]是文本串T,n是T的长度*/
int j = ;
while (j < n&& j < m&& x[j] == x[j]) j++;
extend[] = j;
/*用while循环寻找以T[0]为起点的后缀与P的最长公共前缀*/
int k = ;
for (int i = ; i < n; i++)
{
int p = extend[k] + k - ;
int L = e_Next[i - k];
if (i + L < p + )
{
extend[i] = L;
}
else
{
j = max(, p - i + );
while (i + j < n&& j < m&& y[i + j] == x[j]) j++;
extend[i] = j;
k = i;
}
}
}
char ss_0[maxn];
char ss_1[maxn];
int Next[maxn];
int e_Next[maxn];
int extend[maxn];
int KMP();
int E_KMP();
int main()
{
int menu;
printf("\n\tKMP,选择0\n\te-KMP,选择1\n\t请选择:");
scanf_s("%d", &menu);
if (menu == )
{
int x= KMP();
if (x< ) printf("\n\t错误\n");
}
else if (menu == )
{
int x= E_KMP();
if (x< ) printf("\n\t错误\n");
}
else
{
printf("\n\t错误\n");
}
system("pause");
return ;
}
int KMP()
{
/*可直接修改函数名,为KMP的主函数*/
system("cls");
cin >> ss_0;
cin >> ss_1;
int len_0 = strlen(ss_0);
int len_1 = strlen(ss_1);
Get_Next(ss_0, len_0, Next);
int tmp= KMP_Count(ss_0, len_0, ss_1, len_1, Next);
printf("%d\n", tmp);
return ;
}
int E_KMP()
{
/*可直接修改函数名,为扩展KMP的主函数*/
system("cls");
cin >> ss_0;
cin >> ss_1;
int len_0 = strlen(ss_0);
int len_1 = strlen(ss_1);
Get_e_Next(ss_0, len_0, e_Next);
e_KMP(ss_0, len_0, ss_1, len_1, e_Next, extend);
for (int i = ; i < len_1; i++)
{
printf("%d%c", extend[i], i == len_1 - ? '\n' : ' ');
}
system("pause");
return ;
}

KMP与e-KMP【带注释版】

/*vs 2017/ vs code以外编译器,去掉windows.h头文件和system("pause");*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<Windows.h>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = ; /* KMP */
void Get_Next(char x[], int m, int Next[])
{
/*x[]为模式串P, m为模式串P的长度*/
int i = , j;
j = Next[] = -;
while (i < m)
{
while (- != j && x[i] != x[j]) j = Next[j];
Next[++i] = ++j;
}
}
int KMP_Count(char x[], int m, char y[], int n, int Next[])
{
/*x[]为模式串P,m为P的长度;y[]为文本串T,n为T的长度*/
int i, j;
i = j = ;
int cnt = ;
while (i < n)
{
while (- != j && y[i] != x[j]) j = Next[j];
++i; ++j;
if (j >= m)
{
++cnt;
j = Next[j];
}
}
return cnt;
} /* 扩展KMP */
void Get_e_Next(char x[], int m, int e_Next[])
{
/*x[]为模式串P;m是P的长度;e_Next[i]表示模式串P中,
以P[i]为起点的后缀与模式串P的最长公共前缀的长度*/
e_Next[] = m;
int j = ;
while (j + < m&& x[j] == x[j + ]) j++;
e_Next[] = j;
int k = ;
for (int i = ; i < m; i++)
{
int p = k+ e_Next[k] - ;
int L = e_Next[i - k];
if (i + L <= p)
{
e_Next[i] = L;
}
else
{
j = max(, p - i + );
while (i + j < m&& x[i + j] == x[j]) j++;
e_Next[i] = j;
k = i;
}
}
}
void e_KMP(char x[], int m, char y[], int n, int e_Next[], int extend[])
{
/*x[]是模式串P,m是P的长度,y[]是文本串T,n是T的长度*/
int j = ;
while (j < n&& j < m&& x[j] == x[j]) j++;
extend[] = j;
int k = ;
for (int i = ; i < n; i++)
{
int p = extend[k] + k - ;
int L = e_Next[i - k];
if (i + L < p + )
{
extend[i] = L;
}
else
{
j = max(, p - i + );
while (i + j < n&& j < m&& y[i + j] == x[j]) j++;
extend[i] = j;
k = i;
}
}
}
char ss_0[maxn];
char ss_1[maxn];
int Next[maxn];
int e_Next[maxn];
int extend[maxn];
int KMP();
int E_KMP();
int main()
{
int menu;
printf("\n\tKMP,选择0\n\te-KMP,选择1\n\t请选择:");
scanf_s("%d", &menu);
if (menu == )
{
int x= KMP();
if (x< ) printf("\n\t错误\n");
}
else if (menu == )
{
int x= E_KMP();
if (x< ) printf("\n\t错误\n");
}
else
{
printf("\n\t错误\n");
}
system("pause");
return ;
}
int KMP()
{
/*可直接修改函数名,为KMP的主函数*/
system("cls");
cin >> ss_0;
cin >> ss_1;
int len_0 = strlen(ss_0);
int len_1 = strlen(ss_1);
Get_Next(ss_0, len_0, Next);
int tmp= KMP_Count(ss_0, len_0, ss_1, len_1, Next);
printf("%d\n", tmp);
return ;
}
int E_KMP()
{
/*可直接修改函数名,为扩展KMP的主函数*/
system("cls");
cin >> ss_0;
cin >> ss_1;
int len_0 = strlen(ss_0);
int len_1 = strlen(ss_1);
Get_e_Next(ss_0, len_0, e_Next);
e_KMP(ss_0, len_0, ss_1, len_1, e_Next, extend);
for (int i = ; i < len_1; i++)
{
printf("%d%c", extend[i], i == len_1 - ? '\n' : ' ');
}
system("pause");
return ;
}

KMP与e-KMP【无注释版】

End;

字符串系列——KMP模板整理的更多相关文章

  1. ACM算法模板整理

    史诗级ACM模板整理 基本语法 字符串函数 istream& getline (char* s, streamsize n ); istream& getline (char* s, ...

  2. cf244D. Match &amp; Catch 字符串hash (模板)或 后缀数组。。。

    D. Match & Catch 能够用各种方法做.字符串hash.后缀数组,dp.拓展kmp,字典树.. . 字符串hash(模板) http://blog.csdn.net/gdujian ...

  3. kmp模板 && 扩展kmp模板

    kmp模板: #include <bits/stdc++.h> #define PB push_back #define MP make_pair using namespace std; ...

  4. 洛谷-p5410-扩展KMP模板

    链接: https://www.luogu.org/problem/P5410#submit 题意: 有两个字符串aa,bb,要求输出bb与aa的每一个后缀的最长公共前缀 思路: 扩展kmp模板, 上 ...

  5. Flask开发系列之模板

    Flask开发系列之模板 本文对<FlaskWeb开发:基于python的Web应用开发实战>模板一节做的总结. Jinja2模板引擎 模板 模板是一个包含响应文本的文件,其中包含用占位变 ...

  6. hdu 1686 KMP模板

    // hdu 1686 KMP模板 // 没啥好说的,KMP裸题,这里是MP模板 #include <cstdio> #include <iostream> #include ...

  7. (原创)Python字符串系列(1)——str对象

    在本博客 <Python字符串系列> 中,将介绍以下内容: Python内置的str对象及操作 字符串的格式化 Python中的正则表达式 re模块 本文将介绍Python内置的 str ...

  8. Oulipo HDU 1686 KMP模板

    题目大意:求模式串在主串中的出现次数. 题目思路:KMP模板题 #include<iostream> #include<algorithm> #include<cstri ...

  9. CCF系列之模板生成系统( 201509-3 )

    试题名称: 模板生成系统 试题编号: 201509-3 时间限制: 1.0s 内存限制: 256.0MB 问题描述 成成最近在搭建一个网站,其中一些页面的部分内容来自数据库中不同的数据记录,但是页面的 ...

随机推荐

  1. 【转载pku】三十分钟掌握STL

    三十分钟掌握STL 这是本小人书.原名是<using stl>,不知道是谁写的.不过我倒觉得很有趣,所以化了两个晚上把它翻译出来.我没有对翻译出来的内容校验过.如果你没法在三十分钟内觉得有 ...

  2. POJ2503 Babelfish map或者hash_map

    POJ2503 这是一道水题,用Map轻松AC. 不过,可以拿来测一下字符串散列, 毕竟,很多情况下map无法解决的映射问题需要用到字符串散列. 自己生成一个质数, 随便搞一下. #include&l ...

  3. IJ:Eclipse快捷键大全

    ylbtech-IJ:Eclipse快捷键大全 1.返回顶部 1. Ctrl+1 快速修复(最经典的快捷键,就不用多说了)Ctrl+D: 删除当前行 Ctrl+Alt+↓ 复制当前行到下一行(复制增加 ...

  4. is not mapped [from错误

    我出现的错误是:org.hibernate.hql.ast.QuerySyntaxException: loginuser is not mapped [from loginuser] 配置文件如下: ...

  5. Rails5 View Document

    更新: 2017/06/11 更新: 2017/06/15 加粗,submit必须放在form_for内部 更新: 2017/06/23 对待完成的追加# TODO:                 ...

  6. Spring中bean的作用域与生命周期

    在 Spring 中,那些组成应用程序的主体及由 Spring IOC 容器所管理的对象,被称之为 bean.简单地讲,bean 就是由 IOC 容器初始化.装配及管理的对象,除此之外,bean 就与 ...

  7. video 能播放声音不能播放视频,黑屏

    与视频编码格式有关,mp4的视频编码有三种:MPEG4(DivX),MPEG4(Xvid),AVC(H264). 浏览器播放视频的支持有限,MP4格式的视频只支持h.264的视频: 视频编码: AVC ...

  8. 全面学习ORACLE Scheduler特性(12)使用Windows和Window Groups

    七.使用Windows 此Windows非彼Windows,通常说的Windows是指盖首富的操作系统,而此处所说的Windows,是指SCHEDULER特性中的一个子项.在SCHEDULER中,WI ...

  9. 365 Water and Jug Problem 水壶问题

    有两个容量分别为 x升 和 y升 的水壶以及无限多的水.请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水?如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水.你允许:    装满任 ...

  10. 网站开发综合技术 HTML

    HTML            内容(Hyper Text Markup Language,超文本标记语言) CSS             网页美化 Javascript      脚本语言 第一部 ...