邝斌的ACM模板(KMP算法)
2017-08-12 11:46
399 查看
本博客整理自邝斌的ACM模板
1.1、KMP 算法
经典题目:POJ 3167
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; }
相关文章推荐
- 邝斌的ACM模板(素数)
- 邝斌的ACM模板(目录篇)
- 邝斌的ACM模板(素数筛选和合数分解)
- 邝斌的ACM模板(扩展 KMP)
- 邝斌的ACM模板(扩展欧几里得算法(求 ax+by=gcd 的解以及逆元素))
- 邝斌的ACM模板(求逆元)
- 邝斌的ACM模板(整数拆分)
- 邝斌的ACM模板(Manacher 最长回文子串)
- 邝斌的ACM模板(模线性方程组)
- 邝斌的ACM模板(求 A^B 的约数之和对 MOD 取模)
- 邝斌的ACM模板(AC 自动机)
- 邝斌的ACM模板(随机素数测试和大数分解(POJ 1811) )
- 邝斌的ACM模板(莫比乌斯反演)
- 邝斌的ACM模板(欧拉函数)
- 邝斌的ACM模板(Baby-Step Giant-Step)
- ACM_模板_KMP算法
- 邝斌的ACM模板(高斯消元(浮点数))
- 邝斌的ACM模板(自适应 simpson 积分)
- 邝斌的ACM模板(FFT)
- 邝斌的ACM模板(高斯消元法求方程组的解)