邝斌的ACM模板(KMP算法)

来源:互联网 发布:java字符串转换为数组 编辑:程序博客网 时间:2024/06/05 18:47

本博客整理自邝斌的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;}