zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",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
    ",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
    ",len == L? L:0);
            else printf("%d
    ",len - L%len);
        }
        return 0;
    }
  • 相关阅读:
    .NET 去除一段文本中的HTML标记
    C#实现控件拖动窗口
    使用window.showModalDialog弹出窗口返回值(兼容IE、FF、chrome)
    IE浏览器报错出现stack overflow at line 0的解决办法
    用Python作GIS:原料篇
    winform 自定义控件:半透明Loading控件
    WPF 跟随鼠标动画 by wgscd
    C# 多线程 HTTP request
    VS2015 安装XAN
    C# 用QQ企业邮箱发邮件
  • 原文地址:https://www.cnblogs.com/wxx23-IOU/p/13865965.html
Copyright © 2011-2022 走看看