zoukankan      html  css  js  c++  java
  • KMP

    KMP

    inline void get_next(char *a)
    {
        int n=strlen(a+1);
        next[1]=0;
        for(int i=2,j=0;i<=n;++i)
        {
            while(j>0&&a[i]!=a[j+1]) j=next[j];
            if(a[i]==a[j+1]) ++j;
            next[i]=j; 
        }               
    }
    inline void KMP(char *a,char *b)//a是文本串,b是模式串
    {
        int n=strlen(a+1);
        int m=strlen(b+1);
        for(int i=1,j=0;i<=n;++i)
        {
            while(j>0&&(j==m||a[i]!=b[j+1])) j=next[j];
            if(a[i]==b[j+1]) ++j;
            f[i]=j; 
            if(f[i]==m) cout<<i-m+1<<endl;
        }
    }

    安利一道比较好的对next数组理解的题

    [POI2006]OKR-Periods of Words

    测试点信息源代码
    源代码 复制
    #include<bits/stdc++.h>
    #define db double
    #define RE register
    #define ll long long
    #define P=1000000009
    #define INF 1000000000
    #define get(x) x=read()
    #define pair<ll,int> PLI
    #define pb(x) push_back(x)
    #define pair<int,int> PII
    #define ull unsigned long long
    #define put(x) printf("%d
    ",x)
    #define getc(a) scanf("%s",a+1)
    #define putl(x) printf("%lld
    ",x)
    #define rep(i,x,y) for(RE int i=x;i<=y;++i)
    #define fep(i,x,y) for(RE int i=x;i>=y;--i)
    #define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
    using namespace std;
    const int N=1e6+10;
    int next[N],n,f[N];//f[i]表示以i为结尾的后缀与从1开始的前缀最短的匹配长度. 
    char c[N];
    inline int read()
    {
        int x=0,ff=1;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*ff;
    }
    inline void get_next()
    {
        int j=0;next[1]=0;f[1]=n;
        rep(i,2,n)
        {
            while(j>0&&c[i]!=c[j+1]) j=next[j];
            if(c[i]==c[j+1]) ++j;
            next[i]=j;
            if(next[i]==0) f[i]=n;
            else if(f[next[i]]==n) f[i]=next[i];
            else f[i]=f[next[i]];  
        }
    }
    int main()
    {
    //    freopen("1.in","r",stdin);
        get(n);getc(c);
        get_next();
        ll ans=0;
        rep(i,1,n) 
        {
            if(f[i]==n) continue;
            else ans+=i-f[i];
        }
        //rep(i,1,n) cout<<i<<' '<<next[i]<<endl;
        putl(ans);
        return 0;
    }
    View Code

    [NOI2014]动物园

    这个题真的是头疼....

    调了尽两个小时尽然是自己模数取错了.....

    我们发现暴力跳next是不行的,那我们思考怎么优化。

    我们可以想到我们只要一直维护j<=i/2即可。

    #include<bits/stdc++.h>
    #define db double
    #define RE register
    #define ll long long
    #define P 1000000007
    #define INF 1000000000
    #define get(x) x=read()
    #define pair<ll,int> PLI
    #define pb(x) push_back(x)
    #define pair<int,int> PII
    #define ull unsigned long long
    #define put(x) printf("%d
    ",x)
    #define getc(a) scanf("%s",a+1)
    #define putl(x) printf("%lld
    ",x)
    #define rep(i,x,y) for(RE int i=x;i<=y;++i)
    #define fep(i,x,y) for(RE int i=x;i>=y;--i)
    #define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
    using namespace std;
    const int N=1000010;
    int next[N],g[N];
    char c[N]; 
    ll ans=1;
    inline int read()
    {
        int x=0,ff=1;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*ff;
    }
    inline void get_next()
    {
        int n=strlen(c+1);
        int j=0;g[1]=0;g[0]=-1;
        rep(i,2,n)
        {
            while(j>0&&c[i]!=c[j+1]) j=next[j];
            if(c[i]==c[j+1]) ++j;
            next[i]=j;g[i]=g[j]+1;
        }
    }
    inline void get_num()
    {
        int n=strlen(c+1);
        int j=0;
        rep(i,2,n)
        {
            while(j>0&&c[i]!=c[j+1]) j=next[j];
            if(c[i]==c[j+1]) ++j;
            while((j<<1)>i) j=next[j];
            ans=(ans*(ll)(g[j]+2))%P;
        }
    }
    int main()
    {
        freopen("1.in","r",stdin);
        int get(T);
        while(T--)
        {
            memset(g,0,sizeof(g));
            getc(c);get_next();
            ans=1;
            get_num();
            putl(ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    mongodb添加登录验证--副本集环境
    kibana添加认证及权限--elasticsearch集群版
    Rabbitmq之exchange
    Elasticsearch集群下安装IK中文分词器
    cerebro安装--Elastic Stack之三
    elasticsearch-head安装方法--Elastic Stack之二
    动画小记——点击头像逐渐放大
    埋点
    picasso Failed to decode stream.
    记Sniper
  • 原文地址:https://www.cnblogs.com/gcfer/p/11022726.html
Copyright © 2011-2022 走看看