算法笔记--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中的第六位. 现在的任务就是求得部分匹配表. 问题:怎么得到部分匹 ...
随机推荐
- linux lvs
- HashMap(JDK1.9)详解
一.HashMap的概念. 1.HashMap类的继承实现关系如下:因此HashMap的功能有:可序列化.可克隆等功能. 2.HashMap的数据结构:数组+链表+红黑树. 3.键值对的存储方案:第一 ...
- mysql性能优化2
sql语句优化 性能不理想的系统中除了一部分是因为应用程序的负载确实超过了服务器的实际处理能力外,更多的是因为系统存在大量的SQL语句需要优化. 为了获得稳定的执行性能,SQL语句越简单越好.对复杂的 ...
- cocoapods 配置
二.CocoaPods 安装 CocoaPods可以方便地通过Mac自带的RubyGems安装. 打开Terminal(Mac电脑自带的终端): (1).设置ruby的软件源 这是因为ruby的软件源 ...
- linux常用命令:Linux 文件类型与扩展名
Linux文件类型和Linux文件的文件名所代表的意义是两个不同的概念.我们通过一般应用程序而创建的比如file.txt.file.tar.gz ,这些文件虽然要用不同的程序来打开,但放在Linux文 ...
- Linux基础命令---显示文本grep
grep 按照指定的模式,在文件中搜索匹配的行,将结果显示在标准输出.另外还有两个指令egrep相当于grep –E,fgrep相当于grep -F.如果没有给出文件名,那么从标准输入读取. 此命令的 ...
- Linux基础命令---mknod
mknod 创建块设备或者字符设备文件.此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE.openSUSE.Fedora. 1.语法 mknod [选项] ...
- JavaScript中几种 获取元素的方式
1.根据id获取元素 document.getElementById("id属性的值"); 2.根据标签名字获取元素 document.getElementsByTagName(& ...
- MySQL索引类型总结和使用技巧
引用地址:http://www.jb51.net/article/49346.htm 在数据库表中,对字段建立索引可以大大提高查询速度.假如我们创建了一个 mytable表: 复制代码 代码如下: C ...
- 20145122 《Java程序设计》第8周学习总结
教材学习内容总结 1.NIO使用频道(channel)来衔接数据节点,对数据区的标记提供了clear(),rewind(),flip(),compact()等高级操作. 2.想要取得channel的操 ...