KMP

KMP算法,刚开始看会有些难理解,这个其实多看几遍就好了,有关KMP的介绍也挺多的,在这里就不重复了,点击这里

这里扩展KMP(Z函数),点击这里

列举几道模板题:

HDOJ- 1711 Number Sequence(经典模板题)

#include<map>
#include<set>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdlib>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
using namespace std;
#define ms(x,n) memset(x,n, sizeof(x));
typedef long long LL;
const int inf = 1<<30;
const LL maxn = 1e6+10;

int s1[maxn],s2[maxn],n,m;
int nex[maxn];
void getNext(){  //前缀函数(滑步函数
    int i=1 ,j=0;
    while(i < m){
        if(j==0 || s2[i] == s2[j]){ //(全部不相等从新匹配 || 相等继续下次匹配
            i++, j++;
            if(s2[i]!= s2[j]) nex[i] = j;
            else nex[i] = nex[j];
        }
        else j = nex[j];  //子串移动到第nextval[j]个字符和主串相应字符比较
    }
}

int kmp(){
    getNext();
    int i=1, j=1 ;
    while(i <=n && j<=m ){
        if(s1[i] == s2[j] || j==0) i++,j++;
        else j = nex[j];
    }
    if(j > m) return i-m;
    else return -1;
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        ms(s1, 0);
        ms(s2,0);
        ms(nex,0);
        scanf("%d%d",&n,&m);
        for(int i=1 ;i<=n ;i++)
          scanf("%d",&s1[i]);
        for(int j=1 ;j<=m ;j++)
          scanf("%d",&s2[j]);
      printf("%d\n",kmp());
    }
    return 0;
}

 

HDOJ-1686 Oulipo(经典模板题)

#include<cstdio>
#include<cstring>
char s1[1000010],s2[10010];
int next[10010] = {-1};

void getNext(char p[],int len){
    int i,j=-1;
    for(i=1 ;i<len; i++){
        while(j!=-1 && p[i]!=p[j+1]) j= next[j];
        if(p[i] == p[j+1]) j++;
        next[i] = j;
    }
}

int kmp(char t[],char p[], int len1, int len2){
    int i,j=-1;
    int count = 0;
    getNext(p,len2);
    for(i=0 ;i<len1 ;i++){
        while(j!=-1 && t[i] != p[j+1]){
            j=next[j];
        }
        if(t[i] == p[j+1]) j++;
        if(j == len2-1)
        count++;
    }
    return count;
}

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%s%s",s2,s1);
        printf("%d\n",kmp(s1,s2,strlen(s1), strlen(s2)));
    }
    return 0;
}

 

 

HDOJ-2087 剪花布条

#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
#define Max 1000005
int nex[Max];
int sum;

void GetNext(string t){
    int i = 0;
    int j=-1;
    while(i < (int)t.size()){
        if(j == -1 || t[i] == t[j]){
            i++;  j++;
            nex[i] = j;
        }
        else j = nex[j];
    }
}

void Kmp(string s1,string s2){
    GetNext(s2);
    int i=0  ,j=0;
    int slen = (int)s1.size();
    int tlen = (int)s2.size();
    while(i < slen && j < tlen){
        if(j == -1|| s1[i] == s2[j]){
            if(j == tlen-1){
                sum++;  i++;
                j=0;
            }
            else {
                i++;
                j++;
            }
        }
        else j = nex[j];
    }
}

int main(){
    string s1;
    while(cin >> s1){
            if(s1 == "#")
              break;
            string s2;
            cin >> s2;
            char ch = getchar();
            sum =0;
            nex[0] =-1;
            Kmp(s1,s2);
            printf("%d\n",sum);
        }
        return 0;
}

 

 

HDOJ-3746 Cyclic Nacklace

#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1e5+5;
char s[N];
int n,nex[N], L;
void GetNext(){
    nex[1] = 0;
    for(int i=2 ,j=0 ;i<=L ;i++){
        while(j &&s[i] != s[j+1]) j = nex[j];
        if(s[i] == s[j+1]) j++;
        nex[i] = j;
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1 ;i<=n ;i++){
        scanf("%s",s+1);
        L = strlen(s+1);
        GetNext();
        int len = L - nex[L];
        if(L % len == 0) printf("%d\n",len == L? L:0);
        else printf("%d\n",len - L%len);
    }
    return 0;
}

 

posted @ 2020-10-23 20:10  Jesen等不等式  阅读(165)  评论(0编辑  收藏  举报