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
原文地址:https://www.cnblogs.com/gcfer/p/11022726.html