算法笔记--KMP算法 && EXKMP算法
1.KMP算法
这个博客写的不错:http://www.cnblogs.com/SYCstudio/p/7194315.html
模板:
next数组的求解,那个循环本质就是如果相同前后缀不能加上该位置成就该位置的next数组就一直找相同前后缀的相同前后缀。
求解前缀数组F(也叫next数组):
for (int i=;i<m;i++)
{
int j=F[i-];
while ((B[j+]!=B[i])&&(j>=))
j=F[j];
if (B[j+]==B[i])
F[i]=j+;
else
F[i]=-;
}
利用F数组寻找匹配,这里我们是每找到一个匹配就输出其开始的位置:
while (i<n)
{
if (A[i]==B[j])
{
i++;
j++;
if (j==m)
{
printf("%d\n",i-m+);
j=F[j-]+;
}
}
else
{
if (j==)
i++;
else
j=F[j-]+;
}
}
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define mem(a,b) memset((a),(b),sizeof(a))
const int N=1e3+;
int f[N]={-};
char a[N*N];
char b[N]; int main()
{
/*ios::sync_with_stdio(false);
cin.tie(0);*/
scanf("%s",a);
scanf("%s",b);
int m=strlen(b);
int n=strlen(a);
for(int i=;i<m;i++)
{
int j=f[i-];
while(b[j+]!=b[i]&&j>=)j=f[j];
if(b[j+]==b[i])f[i]=j+;
else f[i]=-;
} int i=,j=;
while(i<n)
{
if(a[i]==b[j])
{
i++;
j++;
if(j==m)
{
printf("%d\n",i-m+);
j=f[j-]+;
}
}
else
{
if(j==)i++;
else j=f[j-]+;
}
} for(int i=;i<m;i++)
{
printf("%d",f[i]+);
if(i!=m-)printf(" ");
else printf("\n");
}
return ;
}
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define mem(a,b) memset((a),(b),sizeof(a))
const int N=1e6+;
const int M=1e4+;
int f[M]={-};
int a[N];
int b[M]; int main()
{
/*ios::sync_with_stdio(false);
cin.tie(0);*/
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=;i<n;i++)scanf("%d",&a[i]);
for(int i=;i<m;i++)scanf("%d",&b[i]); for(int i=;i<m;i++)
{
int j=f[i-];
while(b[j+]!=b[i]&&j>=)j=f[j];
if(b[j+]==b[i])f[i]=j+;
else f[i]=-;
} int i=,j=;
bool flag=true;
while(i<n)
{
if(a[i]==b[j])
{
i++;
j++;
if(j==m)
{
printf("%d\n",i-m+);
flag=false;
break;
}
}
else
{
if(j==)i++;
else j=f[j-]+;
}
}
if(flag)printf("-1\n");
} return ;
}
用next数组求解最小循环节。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
#define pb push_back
#define mem(a,b) memset((a),(b),sizeof(a))
const int N=1e6+;
int f[N]={-};
char s[N]; int main()
{
/*ios::sync_with_stdio(false);
cin.tie(0);*/
while(scanf("%s",s)!=EOF)
{
if(s[]=='.')break;
int m=strlen(s);
for(int i=;i<m;i++)
{
int j=f[i-];
while(s[j+]!=s[i]&&j>=)j=f[j];
if(s[j+]==s[i])f[i]=j+;
else f[i]=-;
} int t=m-(f[m-]+);
if(m%t)t=m;//如果不整出,那么不存在最小循环节,或者说最小循环节就是字符串本身
printf("%d\n",m/t);
}
return ;
}
例题4:POJ 1961 Period
求每一段的最小循环节。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
#define pb push_back
#define mem(a,b) memset((a),(b),sizeof(a))
const int N=1e6+;
int f[N]={-};
char s[N]; int main()
{
/*ios::sync_with_stdio(false);
cin.tie(0);*/
int n;
int c=;
while(scanf("%d",&n)!=EOF&&n)
{
scanf("%s",s);
c++;
printf("Test case #%d\n",c);
int m=strlen(s);
for(int i=;i<m;i++)
{
int j=f[i-];
while(s[j+]!=s[i]&&j>=)j=f[j];
if(s[j+]==s[i])f[i]=j+;
else f[i]=-;
int t=i-f[i];
if((i+)%t==&&(i+)/t>)printf("%d %d\n",i+,(i+)/t);
}
printf("\n");
}
return ;
}
对差值进行匹配
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a)) const int N=2e5+;
int F[N]={-},A[N],B[N];
int main(){
ios::sync_with_stdio(false);
cin.tie();
int n,m;
cin>>n>>m;
for(int i=;i<n;i++)cin>>A[i];
for(int i=n-;i>=;i--)A[i]=A[i]-A[i-];
A[]=;
for(int i=;i<m;i++)cin>>B[i];
for(int i=m-;i>=;i--)B[i]=B[i]-B[i-];
if(m==){
cout<<n<<endl;
return ;
}
for(int i=;i<m;i++)B[i-]=B[i];
m--;
for(int i=;i<m;i++)
{
int j=F[i-];
while(B[j+]!=B[i]&&j>=)j=F[j];
if(B[j+]==B[i])F[i]=j+;
else F[i]=-;
}
int cnt=;
/*for(int i=0;i<n;i++)cout<<A[i]<<' ';
cout<<endl;
for(int i=0;i<m;i++)cout<<B[i]<<' ';
cout<<endl;
for(int i=0;i<m;i++)cout<<F[i]<<' ';
cout<<endl;*/
int i=,j=;
while (i<n)
{
if (A[i]==B[j])
{
i++;
j++;
if (j==m)
{
cnt++;
j=F[j-]+;
}
}
else
{
if (j==)
i++;
else
j=F[j-]+;
}
//cout<<i<<' '<<j<<endl;
}
cout<<cnt<<endl;
return ;
}
2.exkmp算法
https://blog.csdn.net/dyx404514/article/details/41831947
模板:
const int N = 1e6 + ;
int nxt[N], ex[N];
void GETNEXT(char *str) {
int i = , j, po, len=strlen(str);
nxt[] = len;
while(str[i] == str[i+] && i+ < len) i++;
nxt[] = i;
po = ;
for(i = ; i < len; i++) {
if(nxt[i-po] + i < nxt[po] + po)
nxt[i] = nxt[i-po];
else {
j=nxt[po] + po - i;
if(j < ) j = ;
while(i + j < len && str[j] == str[j+i])
j++;
nxt[i] = j;
po = i;
}
}
}
void EXKMP(char *s1,char *s2)
{
int i = , j, po, len = strlen(s1), l2=strlen(s2);
GETNEXT(s2);
while(s1[i] == s2[i] && i < l2 && i < len) i++;
ex[] = i;
po = ;
for(i = ; i < len; i++)
{
if(nxt[i-po] + i < ex[po] + po) ex[i]=nxt[i-po];
else {
j = ex[po] + po - i;
if(j < ) j = ;
while(i + j < len && j < l2 && s1[j+i] == s2[j]) j++;
ex[i] = j;
po = i;
}
}
}
HDU 2594 Simpsons’ Hidden Talents
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head const int N = ;
int nxt[N], ex[N];
char s[N], t[N];
void GETNEXT(char *str) {
int i = , j, po, len = strlen(str);
nxt[] = len;
while(str[i] == str[i+] && i+ < len) i++;
nxt[] = i;
po = ;
for(i = ; i < len; i++) {
if(nxt[i-po] + i < nxt[po] + po)
nxt[i] = nxt[i-po];
else {
j=nxt[po] + po - i;
if(j < ) j = ;
while(i + j < len && str[j] == str[j+i])
j++;
nxt[i] = j;
po = i;
}
}
}
void EXKMP(char *s1,char *s2)
{
int i = , j, po, len = strlen(s1), l2 = strlen(s2);
GETNEXT(s2);
while(s1[i] == s2[i] && i < l2 && i < len) i++;
ex[] = i;
po = ;
for(i = ; i < len; i++)
{
if(nxt[i-po] + i < ex[po] + po) ex[i]=nxt[i-po];
else {
j = ex[po] + po - i;
if(j < ) j = ;
while(i + j < len && j < l2 && s1[j+i] == s2[j]) j++;
ex[i] = j;
po = i;
}
}
}
int main() {
while(~scanf("%s", &s)) {
scanf("%s", &t);
EXKMP(t, s);
int len = strlen(t), res = ;
for (int i = ; i < len; ++i) {
if(ex[i]+i == len) {
res = ex[i];
break;
}
}
for (int i = ; i < res; ++i) putchar(s[i]);
if(res)putchar(' ');
printf("%d\n", res);
}
return ;
}
void FFT_match(char *s1,char *s2,int m,int n)
{
reverse(ss1,ss1+m);
for(int i=;i<m;i++) A[i]=(s1[i]!='*')?(s1[i]-'a'+):;
for(int i=;i<n;i++) B[i]=(s2[i]!='*')?(s2[i]-'a'+):; for(int i=;i<len;i++) a[i]=Comp(A[i]*A[i]*A[i],),b[i]=Comp(B[i],);
FFT(a,len,);FFT(b,len,);
for(int i=;i<len;i++) P[i]=P[i]+a[i]*b[i]; for(int i=;i<len;i++) a[i]=Comp(A[i],),b[i]=Comp(B[i]*B[i]*B[i],);
FFT(a,len,);FFT(b,len,);
for(int i=;i<len;i++) P[i]=P[i]+a[i]*b[i]; for(int i=;i<len;i++) a[i]=Comp(A[i]*A[i],),b[i]=Comp(B[i]*B[i],);
FFT(a,len,);FFT(b,len,);
for(int i=;i<len;i++) P[i]=P[i]-a[i]*b[i]*Comp(,); FFT(P,len,-);
for(int i=m-;i<n;i++) if(fabs(P[i].r)<=1e-) printf("%d ",i-m+);
}
算法笔记--KMP算法 && EXKMP算法的更多相关文章
- <算法笔记>关于快速排序的算法优化排序(顺便给百度百科纠个错)
快速排序是排序算法之中的基本中的基本,虽然越来越多的接口函数将快速排序“完美的封装了起来”,比如C++中的qsort或者<algorithm>中的sort(与stable_sort相对应) ...
- 算法笔记之KMP算法
本文是<算法笔记>KMP算法章节的阅读笔记,文中主要内容来源于<算法笔记>.本文主要介绍了next数组.KMP算法及其应用以及对KMP算法的优化. KMP算法主要用于解决字符串 ...
- 算法:KMP算法
算法:KMP排序 算法分析 KMP算法是一种快速的模式匹配算法.KMP是三位大师:D.E.Knuth.J.H.Morris和V.R.Pratt同时发现的,所以取首字母组成KMP. 少部分图片来自孤~影 ...
- BF算法与KMP算法
BF(Brute Force)算法是普通的模式匹配算法,BF算法的思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配,若相等,则继续比较S的第二个字符和 T的第二个字符:若不相等,则比较S的 ...
- 机器学习实战 - 读书笔记(12) - 使用FP-growth算法来高效发现频繁项集
前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第12章 - 使用FP-growth算法来高效发现频繁项集. 基本概念 FP-growt ...
- 机器学习实战 - 读书笔记(11) - 使用Apriori算法进行关联分析
前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第11章 - 使用Apriori算法进行关联分析. 基本概念 关联分析(associat ...
- 决策树笔记:使用ID3算法
决策树笔记:使用ID3算法 决策树笔记:使用ID3算法 机器学习 先说一个偶然的想法:同样的一堆节点构成的二叉树,平衡树和非平衡树的区别,可以认为是"是否按照重要度逐渐降低"的顺序 ...
- 学习Java 以及对几大基本排序算法(对算法笔记书的研究)的一些学习总结(Java对算法的实现持续更新中)
Java排序一,冒泡排序! 刚刚开始学习Java,但是比较有兴趣研究算法.最近看了一本算法笔记,刚开始只是打算随便看看,但是发现这本书非常不错,尤其是对排序算法,以及哈希函数的一些解释,让我非常的感兴 ...
- 第四十一课 KMP子串查找算法
问题: 右移的位数和目标串没有多大的关系,和子串有关系. 已匹配的字符数现在已经有了,部分匹配值还没有. 前六位匹配成功就去查找PMT中的第六位. 现在的任务就是求得部分匹配表. 问题:怎么得到部分匹 ...
随机推荐
- 做报表需要知道的基本的SQL语句
为客户做报表需要操作数据库,基本的SQL是必须要掌握的,下面介绍做报表最常用的SQL语句. 方法/步骤 1 查询数据:编号表示查询顺序. (8) select (9) distinct (11 ...
- 026-chmod命令
语法# chmod [ 选项参数 ] 选择修改权限的对象 权限的改变 目标文件 语义:对哪些目标文件的哪些权限进行修改. (1)# chmod -R ugo +r /home/apple.将 ...
- java opencv使用相关
Using OpenCV Java with Eclipse http://docs.opencv.org/2.4/doc/tutorials/introduction/java_eclipse/ja ...
- Applying the Kappa architecture in the telco industry
https://www.oreilly.com/ideas/applying-the-kappa-architecture-in-the-telco-industry Kappa architectu ...
- silverlight数据绑定
控件绑定 <Grid x:Name="LayoutRoot"> <StackPanel> <ScrollBar x:Name="bar&qu ...
- win7 安装.Net framework 4.0出现 安装不成功,错误代码0x80240037 的解决方法
1.安装说明 系统:win7 64位 安装包:dotNetFx40_Full_x86_x64.exe(.Net framework 4.0) 出现的问题:在win7 上安装dotNetFx40_Ful ...
- ELK学习笔记之Logstash和Filebeat解析对java异常堆栈下多行日志配置支持
0x00 概述 logstash官方最新文档.假设有几十台服务器,每台服务器要监控系统日志syslog.tomcat日志.nginx日志.mysql日志等等,监控OOM.内存低下进程被kill.ngi ...
- mysql服务器,大量tcp连接状态TIME_WAIT
今天早上,java应用中发现too many open files,检查了下使用的连接数发现基本上在两三百左右,mysql打开的文件数也就几百左右,再看所有tcp连接,发现3306的连接有4000多, ...
- CSS3 转换
CSS3 转换 版权声明:未经博主授权,内容严禁转载 什么是转换 转换时使元素改变形状.尺寸和位置的一种效果. 可以对元素应用 2D 或 3D 转换,从而对元素进行旋转.缩放.移动或倾斜. 2D 转换 ...
- 20145318《网络对抗》注入shellcode及Return-to-libc
20145318<网络对抗>注入shellcode及Return-to-libc 注入shellcode 知识点 注入shellcodeShellcode实际是一段代码(也可以是填充数据) ...