您的位置:首页 > 其它

邝斌的ACM模板(KMP算法)

2017-08-12 11:46 399 查看
本博客整理自邝斌的ACM模板

1.1、KMP 算法

/*
* next[]的含义:x[i-next[i]...i-1]=x[0...next[i]-1]
* next[i]为满足x[i-z...i-1]=x[0...z-1]的最大z值(就是x的自身匹配)
*/
void kmp_pre(char x[],int m,int next[])
{
int i,j;
j=next[0]=-1;
i=0;
while(i<m)
{
while(-1!=j && x[i]!=x[j])j=next[j];
next[++i]=++j;
}
}
/*
* kmpNext[]的意思:next'[i]=next[next[...[next[i]]]] (直到next'[i]<0或者 x[next'[i]]!=x[i])
* 这样的预处理可以快一些
*/
void preKMP(char x[],int m,int kmpNext[])
{
int i,j;
j=kmpNext[0]=-1;
i=0;
while(i<m)
{

while(-1!=j && x[i]!=x[j])j=kmpNext[j];
if(x[++i]==x[++j])kmpNext[i]=kmpNext[j];
else kmpNext[i]=j;
}
}
/*
* 返回x在y中出现的次数,可以重叠
*/
int next[10010];
int KMP_Count(char x[],int m,char y[],int n)
{
//x是模式串,y是主串
int i,j;
int ans=0;
//preKMP(x,m,next);
kmp_pre(x,m,next);
i=j=0;
while(i<n)
{
while(-1!=j && y[i]!=x[j])j=next[j];
i++;
j++;
if(j>=m)
{
ans++;
j=next[j];
}
}
return ans;
}


经典题目:POJ 3167

/*
* POJ 3167 Cow Patterns
* 模式串可以浮动的模式匹配问题
* 给出模式串的相对大小,需要找出模式串匹配次数和位置
* 比如说模式串:1,4,4,2,3,1 而主串:5,6,2,10,10,7,3,2,9
* 那么2,10,10,7,3,2就是匹配的
*
* 统计比当前数小,和于当前数相等的,然后进行kmp
*/
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
const int MAXN=100010;
const int MAXM=25010;
int a[MAXN];
int b[MAXN];
int n,m,s;
int as[MAXN][30];
int bs[MAXM][30];

void init()
{
for(int i=0; i<n; i++)
{
if(i==0)
{
for(int j=1; j<=25; j++)as[i][j]=0;
}
else
{
for(int j=1; j<=25; j++)as[i][j]=as[i-1][j];
}
as[i][a[i]]++;
}
for(int i=0; i<m; i++)
{
if(i==0)
{
for(int j=1; j<=25; j++)bs[i][j]=0;
}
else
{
for(int j=1; j<=25; j++)bs[i][j]=bs[i-1][j];
}
bs[i][b[i]]++;
}
}
int next[MAXM];
void kmp_pre()
{
int i,j;
j=next[0]=-1;
i=0;
while(i<m)
{
int t11=0,t12=0,t21=0,t22=0;
for(int k=1; k<b[i]; k++)
{
if(i-j>0)t11+=bs[i][k]-bs[i-j-1][k];
else t11+=bs[i][k];
}
if(i-j>0)t12=bs[i][b[i]]-bs[i-j-1][b[i]];
else t12=bs[i][b[i]];

for(int k=1; k<b[j]; k++)
{
t21+=bs[j][k];
}
t22=bs[j][b[j]];
if(j==-1 || (t11==t21&&t12==t22))
{
next[++i]=++j;
}
else j=next[j];
}
}
vector<int>ans;
void kmp()
{
ans.clear();
int i,j;
kmp_pre();
i=j=0;
while(i<n)
{
int t11=0,t12=0,t21=0,t22=0;
for(int k=1; k<a[i]; k++)
{
if(i-j>0)t11+=as[i][k]-as[i-j-1][k];
else t11+=as[i][k];
}
if(i-j>0)t12=as[i][a[i]]-as[i-j-1][a[i]];
else t12=as[i][a[i]];

for(int k=1; k<b[j]; k++)
{
t21+=bs[j][k];
}
t22=bs[j][b[j]];
if(j==-1 || (t11==t21&&t12==t22))
{
i++;
j++;
if(j>=m)
{
ans.push_back(i-m+1);
j=next[j];
}
}
else j=next[j];
}
}
int main()
{
while(scanf("%d%d%d",&n,&m,&s)==3)
{
for(int i=0; i<n; i++)
{
scanf("%d",&a[i]);
}
for(int i=0; i<m; i++)
{
scanf("%d",&b[i]);
}
init();
kmp();
printf("%d\n",ans.size());
for(int i=0; i<ans.size(); i++)    printf("%d\n",ans[i]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: