一些常用模板

· · 个人记录

以下整理了一些常用的算法、技巧、零散知识点等的模板

可能会不定时的进行更新

这也是蒟蒻第一次写博客

如有不完善以及需要补充的地方请指出 谢谢

只要你不失去自己的崇高,整个世界都会为你敞开。

快读:

inline ll read(){   
    ll num=0,f=1;  
    char chr=getchar();
    while(chr<'0'||chr>'9'){   
        if(chr=='-') f=-1;
        chr=getchar();
    }
    while(chr>='0'&&chr<='9'){    
        num=num*10+chr-'0';   
        chr=getchar();
    } 
    return num*f;
}

Kruskal:

#include<bits/stdc++.h>
using namespace std;
const int maxm=2e5+5,maxn=5005;
struct node{
    int u,v,w;
}edge[maxm];
int fa[maxn],n,m,ans,cnt;
bool cmp(node a,node b){
    return a.w<b.w;
}
int find(int x)
{
    if (fa[x]!=x) fa[x]=find(fa[x]);
    return fa[x];
}
void kruskal(){
    sort(edge,edge+m,cmp);
    for(int i=0;i<m;i++){
        if(find(edge[i].u)==find(edge[i].v))            
            continue;
        ans+=edge[i].w;
        fa[find(edge[i].v)]=find(edge[i].u);
        if(++cnt==n-1) break;
    }
}
int main(){
    ios::sync_with_stdio(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=0;i<m;i++)
        cin>>edge[i].u>>edge[i].v>>edge[i].w;
    kruskal();
    if(cnt==n-1) cout<<ans;
    else cout<<"orz";
    return 0;
}

Borůvka (Sollin):

#include<bits/stdc++.h>
using namespace std;
const int maxn=5000+5,maxm=2e5+5;
int n,m;
int u[maxm],v[maxm],w[maxm];
bool used[maxm];
int par[maxn],b[maxn];
int get_par(int x){
    if (x==par[x]) return x;
    else return par[x]=get_par(par[x]);
}
bool Better(int x, int y){
    if(y==0) return true;
    if(w[x]!=w[y]) return w[x]<w[y];
    return x<y;
}
void Boruvka(){
    int merged=0,ans=0;
    bool update=true;
    while(update){
        update=false;
        memset(b,0,sizeof(b));
        for(int i=1;i<=m;++i){
            if(used[i]) continue;
            int p=get_par(u[i]),q=get_par(v[i]);
            if(p==q) continue;
            if(Better(i,b[p])) b[p]=i;
            if(Better(i,b[q])) b[q]=i;
        }
        for(int i=1;i<=n;++i)
            if(b[i]!=0&&used[b[i]]==false){
                update=true;
                merged++; 
                ans+=w[b[i]];
                used[b[i]]=true;
                par[get_par(u[b[i]])]=get_par(v[b[i]]);
            }
    }
    if(merged==n-1) cout<<ans;
    else cout<<"orz";
}

int main(){
    ios::sync_with_stdio(0);
    cin>>n>>m;
    for(int i=1;i<=m;++i)
        cin>>u[i]>>v[i]>>w[i];
    for(int i=1;i<=n;++i) par[i]=i;    
    Boruvka();
    return 0;
}

二进制GC:D :

ll gcd(lla,llb)
{
    if(a==0) return b;
    if(!(a&1)&&!(b&1))
        return 2*gcd(a>>1,b>>1);
    else if(!(a&1))
        return gcd(a>>1,b);
    else if(!(b&1))
        return gcd(a,b>>1);
    else
        return gcd(abs(a-b),min(a,b));
}

结构体重载运算符:

struct node{  
    int x,y;  
    bool operator<(const node &a)const{  
        return x<a.x;  
    }  
};
struct node{
    int x,y;
    bool friend operator<(node a,node b){
        return a.x>b.x;
    }
};

并查集:

初始化:

int fa[MAXN];
inline void init(int n){
    for(int i=1;i<=n;++i) fa[i]=i;
}

查询(路径压缩):

int find(int x){
    if(x==fa[x]) return x;
    else{
        fa[x]=find(fa[x]); 
        return fa[x];         
    }
}
int find(int x){
    return x==fa[x]?x:(fa[x]=find(fa[x]));   //简化版本
}

合并:

inline void merge(int i,int j){
    if(rand()&1) swap(i,j);
    fa[find(i)]=find(j);
}

快速幂:

int fastPow(int x,int y){
    int ans=1;
    while(y!=0){
        if(y&1) ans=ans*x;
        x=x*x;
        y>>=1;
    }
    return ans;
}

Dijkstra无优化:

链式前项星存图

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
ll head[maxn],cnt,dis[maxn],m,n,s,minn;
bool vis[maxn];
struct edge{
    int to,nxt,w;
}edge[maxn];
void addedge(int x,int y,int z){
    edge[++cnt].to=y;
    edge[cnt].w=z;
    edge[cnt].nxt=head[x];
    head[x]=cnt;
}
int main(){
    cin>>n>>m>>s;
    for(int i=1;i<=n;i++) dis[i]=2147483647;
    dis[s]=0;
    for(int i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        addedge(a,b,c);
    }
    int pos=s;
    while(vis[pos]==0){
        minn=2147483647,vis[pos]=1;
        for(int i=head[pos];i!=0;i=edge[i].nxt)
            if(!vis[edge[i].to])
                dis[edge[i].to]=min(dis[edge[i].to],dis[pos]+edge[i].w);
        for(int i=1;i<=n;i++)
            if(dis[i]<minn&&vis[i]==0)
                minn=dis[i],pos=i;
    }
    for(int i=1;i<=n;i++) cout<<dis[i]<<' ';
}

vector存图

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
ll cnt,dis[maxn],m,n,s,minn;
bool vis[maxn];
struct node{
    int to,w;
};
vector<node>edge[maxn];
int main(){
    cin>>n>>m>>s;
    for(int i=1;i<=n;i++) dis[i]=2147483647;
    dis[s]=0;
    for(int i=0;i<m;i++){
        int a;
        node e;
        cin>>a>>e.to>>e.w;
        edge[a].push_back(e);
    }
    int pos=s;
    for(int j=1;j<=n;j++){
        minn=2147483647,vis[pos]=1;
        for(int i=0;i<edge[pos].size();i++)
            if(!vis[edge[pos][i].to])
                dis[edge[pos][i].to]=min(dis[edge[pos][i].to],dis[pos]+edge[pos][i].w);
        for(int i=1;i<=n;i++)
            if(dis[i]<minn&&!vis[i])
                minn=dis[i],pos=i;
    }
    for(int i=1;i<=n;i++) cout<<dis[i]<<' ';
}

Dijkstra堆优化:

链式前项星存图

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
ll head[maxn],cnt,dis[maxn],m,n,s;
bool vis[maxn];
struct edge{
    int to,nxt,w;
}edge[maxn];
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
void addedge(int x,int y,int z){
    edge[++cnt].to=y;
    edge[cnt].w=z;
    edge[cnt].nxt=head[x];
    head[x]=cnt;
}
int main(){
    cin>>n>>m>>s;
    for(int i=1;i<=n;i++) dis[i]=2147483647;
    dis[s]=0;
    for(int i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        addedge(a,b,c);
    }
    q.push(make_pair(0,s));
    while(q.size()){
        int pos=q.top().second;
        q.pop();
        if(vis[pos]) continue;
        vis[pos]=1;
        for(int i=head[pos];i!=0;i=edge[i].nxt)
            if(!vis[edge[i].to]&&dis[edge[i].to]>dis[pos]+edge[i].w){
                dis[edge[i].to]=dis[pos]+edge[i].w;
                q.push(make_pair(dis[edge[i].to],edge[i].to));
            }
    }
    for(int i=1;i<=n;i++) cout<<dis[i]<<' ';
    return 0;
}

vector存图

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
ll cnt,dis[maxn],m,n,s;
bool vis[maxn];
struct node{
    int to,w;
};
vector<node>edge[maxn];
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
int main(){
    cin>>n>>m>>s;
    for(int i=1;i<=n;i++) dis[i]=2147483647;
    dis[s]=0;
    for(int i=1;i<=m;i++){
        int a;
        node e;
        cin>>a>>e.to>>e.w;
        edge[a].push_back(e);
    }
    q.push(make_pair(0,s));
    while(q.size()){
        int pos=q.top().second;
        q.pop();
        if(vis[pos]) continue;
        vis[pos]=1;
        for(int i=0;i<edge[pos].size();i++)
            if(!vis[edge[pos][i].to]&&dis[edge[pos][i].to]>dis[pos]+edge[pos][i].w){
                dis[edge[pos][i].to]=dis[pos]+edge[pos][i].w;
                q.push(make_pair(dis[edge[pos][i].to],edge[pos][i].to));
            }
    }
    for(int i=1;i<=n;i++) cout<<dis[i]<<' ';
    return 0;
}

Floyd

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+5;
int a[maxn][maxn],n,m,s;
int main(){
    cin>>n>>m>>s;
    memset(a,2147483647,sizeof(a));
    for(int i=1,u,v,w;i<=m;i++){
        cin>>u>>v>>w;
        a[u][v]=min(a[u][v],w);
    }
    a[s][s]=0;
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++){
            if(i==k||a[i][k]==2147483647) continue;
            for(int j=1;j<=n;j++)
                a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
        }
    for(int i=1;i<=n;i++) cout<<a[s][i]<<" ";
    return 0;
}

SPFA无优化:

链式前项星存图

#include<bits/stdc++.h>
const int maxn=5e5+5;
using namespace std;
int n,m,s,cnt;
int dis[maxn],head[maxn];
bool vis[maxn];
struct Edge{
    int to,nxt,w;
}edge[maxn]; 
queue<int>q;
void addedge(int x,int y,int z){                              
    edge[++cnt].to=y;
    edge[cnt].w=z;
    edge[cnt].nxt=head[x];
    head[x]=cnt; 
}
int main(){
    cin>>n>>m>>s;
    for(int i=1;i<=n;i++) dis[i]=2147483647;
    for(int i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c; 
        addedge(a,b,c);
    }
    q.push(s);dis[s]=0;vis[s]=1;
    while(!q.empty()){
        int pos=q.front(); 
        q.pop();vis[pos]=0; 
        for(int i=head[pos];i;i=edge[i].nxt){
            if(dis[edge[i].to]>dis[pos]+edge[i].w){
                dis[edge[i].to]=dis[pos]+edge[i].w;
                if(!vis[edge[i].to]){
                    vis[edge[i].to]=1; 
                    q.push(edge[i].to);
                }
            }
        }
    }
    for(int i=1;i<=n;i++) cout<<dis[i]<<" ";
    return 0;
} 

vector存图

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e5+5;
ll cnt,dis[maxn],m,n,s;
bool vis[maxn];
struct node{
    int to,w;
};
vector<node>edge[maxn];
queue<int>q;
int main(){
    cin>>n>>m>>s;
    for(int i=1;i<=n;i++) dis[i]=2147483647;
    for(int i=1;i<=m;i++){
        int a;
        node e;
        cin>>a>>e.to>>e.w;
        edge[a].push_back(e);
    }
    q.push(s);dis[s]=0;vis[s]=1;
    while(!q.empty()){
        int pos=q.front(); 
        q.pop();vis[pos]=0; 
        for(int i=0;i<edge[pos].size();i++){
            if(dis[edge[pos][i].to]>dis[pos]+edge[pos][i].w){
                dis[edge[pos][i].to]=dis[pos]+edge[pos][i].w;
                if(!vis[edge[pos][i].to]){
                    vis[edge[pos][i].to]=1; 
                    q.push(edge[pos][i].to);
                }
            }
        }
    }
    for(int i=1;i<=n;i++) cout<<dis[i]<<' ';
    return 0;
}

Johnson 全源最短路:

#include<bits/stdc++.h>
const int maxn=1e5+5;
using namespace std;
struct Edge{
  int to,nxt,w;
}edge[maxn];
int head[maxn],t[maxn],cnt,n,m;
bool vis[maxn];
long long h[maxn],dis[maxn];
void addedge(int x,int y,int z){
    edge[++cnt].to=y;
    edge[cnt].w=z;
    edge[cnt].nxt=head[x];
    head[x]=cnt;
}
bool spfa(int s){
    queue<int>q;
    memset(h,63,sizeof(h));
    h[s]=0;vis[s]=1;q.push(s);
    while(!q.empty()){
        int pos=q.front();
        q.pop();vis[pos]=0;
        for(int i=head[pos];i;i=edge[i].nxt){
            if(h[edge[i].to]>h[pos]+edge[i].w){
                h[edge[i].to]=h[pos]+edge[i].w;
                if(!vis[edge[i].to]){
                    vis[edge[i].to]=1;
                    q.push(edge[i].to);
                    t[edge[i].to]++;
                    if(t[edge[i].to]==n+1) return false;
                }
            }
        }
    }
    return true;
}
void dijkstra(int s){
    priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
    for(int i=1;i<=n;i++) dis[i]=1e9;
    memset(vis,0,sizeof(vis));
    dis[s] = 0;
    q.push(make_pair(0,s));
    while(!q.empty()){
        int pos=q.top().second;
        q.pop();
        if(vis[pos]) continue;
        vis[pos]=1;
        for(int i=head[pos];i;i=edge[i].nxt)
            if(!vis[edge[i].to]&&dis[edge[i].to]>dis[pos]+edge[i].w){
                dis[edge[i].to]=dis[pos]+edge[i].w;
                q.push(make_pair(dis[edge[i].to],edge[i].to));
            }
    }
    return;
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        addedge(a,b,c);
    }
    for(int i=1;i<=n;i++) addedge(0,i,0);
    if(!spfa(0)){
        cout<<-1<<endl;
        return 0;
    }
    for(int u=1;u<=n;u++)
        for(int v=head[u];v;v=edge[v].nxt) 
            edge[v].w+=h[u]-h[edge[v].to];
    for(int i=1;i<=n;i++){
        dijkstra(i);
        long long ans=0;
        for(int j=1;j<=n;j++){
            if(dis[j]==1e9) ans+=j*1e9;
            else ans+=j*(dis[j]+h[j]-h[i]);
        }
        cout<<ans<<endl;
    }
    return 0;
}

次短路:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
int dis[maxn],dit[maxn];
int n,m,s,t;
struct node{
    int to,w;
};
vector<node>edge[maxn];
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
void addedge(int x,int y,int z){
    node e;
    e.to=y;e.w=z;edge[x].push_back(e);
}
void dijkstra(){
    for(int i=1;i<=n;i++) dis[i]=1e9,dit[i]=1e9;
    dis[s]=0;
    q.push(make_pair(0,s));
    while(!q.empty()){
        int pos=q.top().second;
        q.pop();
        for(int i=0;i<edge[pos].size();i++){
            if(dis[edge[pos][i].to]>=dis[pos]+edge[pos][i].w){
                dis[edge[pos][i].to]=dis[pos]+edge[pos][i].w;
                q.push(make_pair(dis[edge[pos][i].to],edge[pos][i].to));
            }
            else if(dit[edge[pos][i].to]>dis[pos]+edge[pos][i].w){
                dit[edge[pos][i].to]=dis[pos]+edge[pos][i].w;
                q.push(make_pair(dis[edge[pos][i].to],edge[pos][i].to));
            }
            if(dit[edge[pos][i].to]>edge[pos][i].w+dit[pos])
                dit[edge[pos][i].to]=edge[pos][i].w+dit[pos];
        }
    }
}
int main(){
    cin>>n>>m;
    s=1;
    for(int i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        addedge(a,b,c);addedge(b,a,c);
    }
    dijkstra();
    cout<<dit[n];
    return 0;
}

线段树:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=1e6+5;
ll n,m,mod,a[maxn],tree[maxn<<2],lazy_add[maxn<<2],lazy_mul[maxn<<2];
inline ll ls(ll p){return p<<1;}//左子树 
inline ll rs(ll p){return (p<<1)|1;}//右子树 
void build(ll p,ll l,ll r){//建树 
    if(l==r){tree[p]=a[l];lazy_mul[p]=1;tree[p]%=mod;return;}
    ll mid=l+((r-l)>>1);
    build(ls(p),l,mid);
    build(rs(p),mid+1,r);
    tree[p]=tree[ls(p)]+tree[rs(p)];tree[p]%=mod;
    lazy_mul[p]=1;
}
void push_down(ll p,ll nl,ll nr){//懒惰标记 
    if(lazy_mul[p]!=1){
        lazy_mul[ls(p)]*=lazy_mul[p];lazy_mul[ls(p)]%=mod;
        lazy_mul[rs(p)]*=lazy_mul[p];lazy_mul[rs(p)]%=mod;
        lazy_add[ls(p)]*=lazy_mul[p];lazy_add[ls(p)]%=mod;
        lazy_add[rs(p)]*=lazy_mul[p];lazy_add[rs(p)]%=mod;
        tree[ls(p)]*=lazy_mul[p];tree[ls(p)]%=mod;
        tree[rs(p)]*=lazy_mul[p];tree[rs(p)]%=mod;
        lazy_mul[p]=1;
    }
    if(lazy_add[p]){
        ll mid=nl+((nr-nl)>>1);
        lazy_add[ls(p)]+=lazy_add[p];lazy_add[ls(p)]%=mod;
        lazy_add[rs(p)]+=lazy_add[p];lazy_add[rs(p)]%=mod;
        tree[ls(p)]+=(mid-nl+1)*lazy_add[p];tree[ls(p)]%=mod;
        tree[rs(p)]+=(nr-mid)*lazy_add[p];tree[rs(p)]%=mod;
        lazy_add[p]=0;
    }
}
void update_add(ll l,ll r,ll c,ll nl,ll nr,ll p){//区间修改加 
    if(l<=nl&&r>=nr){
        tree[p]+=(nr-nl+1)*c;tree[p]%=mod;
        lazy_add[p]+=c;lazy_add[p]%=mod;
        return;
    }
    ll mid=nl+((nr-nl)>>1);
    push_down(p,nl,nr);
    if(mid>=l) update_add(l,r,c,nl,mid,ls(p));
    if(r>mid) update_add(l,r,c,mid+1,nr,rs(p));
    tree[p]=tree[ls(p)]+tree[rs(p)];tree[p]%=mod;
}
void update_mul(ll l,ll r,ll c,ll nl,ll nr,ll p){//区间修改乘 
    if(l<=nl&&r>=nr){
        tree[p]*=c;tree[p]%=mod;
        lazy_add[p]*=c;lazy_add[p]%=mod;
        lazy_mul[p]*=c;lazy_mul[p]%=mod;
        return;
    }
    ll mid=nl+((nr-nl)>>1);
    push_down(p,nl,nr);
    if(mid>=l) update_mul(l,r,c,nl,mid,ls(p));
    if(r>mid) update_mul(l,r,c,mid+1,nr,rs(p));
    tree[p]=tree[ls(p)]+tree[rs(p)];tree[p]%=mod;
}
ll getsum(ll l,ll r,ll nl,ll nr,ll p){//区间求和 
    if(l<=nl&&r>=nr) return tree[p];
    ll mid=nl+((nr-nl)>>1),sum=0;
    push_down(p,nl,nr);
    if(mid>=l){sum+=getsum(l,r,nl,mid,ls(p));sum%=mod;}
    if(mid<r){sum+=getsum(l,r,mid+1,nr,rs(p));sum%=mod;}
    return sum%mod;
}
int main(){
    ios::sync_with_stdio(0);
    cin>>n>>m>>mod;
    for(int i=1;i<=n;i++){cin>>a[i];a[i]%=mod;}
    build(1,1,n); 
    int index,x,y,k; 
    for(int i=1;i<=m;i++){
        cin>>index;
        if(index==1){
            cin>>x>>y>>k;
            update_mul(x,y,k,1,n,1);
        }
        else if(index==2){
            cin>>x>>y>>k;
            update_add(x,y,k,1,n,1);
        }
        else if(index==3){
            cin>>x>>y;
            cout<<getsum(x,y,1,n,1)<<endl;
        }
    }
    return 0;
}

膜拜zhx

感谢zhx神奇的duantree

#include<bits/stdc++.h>
#define int long long
#define re register
#define il inline
#define lson nowl,mid,pos<<1
#define rson mid+1,nowr,pos<<1|1
#define maxn 100005
#define root 1,n,1
#define zhx 1000000007
#define pos_now nowl,nowr,pos
using namespace std;
int n,m,x,y,k,opt,a[maxn];
il int ls(int pos){return pos<<1;}
il int rs(int pos){return pos<<1|1;}
struct SegMent_Tree{
    int sum;
    int lazy;
    SegMent_Tree(){
        sum=lazy=0;
    }
}t[maxn<<2];
il SegMent_Tree operator+(const SegMent_Tree &ls,const SegMent_Tree &rs){
    SegMent_Tree temp;
    temp.sum=ls.sum+rs.sum;
    //temp.sum%=zhx;
    return temp;
}
il void build(int nowl,int nowr,int pos){//建树 
    if(nowl==nowr){
        t[pos].sum=a[nowl];
        return;
    }
    int mid=(nowl+nowr)>>1;
    build(lson);
    build(rson);
    t[pos]=t[ls(pos)]+t[rs(pos)];
}
il void revise(int nowl,int nowr,int pos,int plus){//修改 
    t[pos].sum+=(nowr-nowl+1)*plus;
    //t[pos].sum%=zhx;
    t[pos].lazy+=plus;
    //t[pos].lzay%=zhx;
}
il void push_down(int nowl,int nowr,int pos){//下放 
    if(t[pos].lazy){
        int mid=(nowl+nowr)>>1;
        revise(lson,t[pos].lazy);
        revise(rson,t[pos].lazy);
        t[pos].lazy=0;
    }
}
il void update(int l,int r,int nowl,int nowr,int pos,int plus){//更新 
    if(l<=nowl&&r>=nowr){
        revise(pos_now,plus);
        return;
    }
    int mid=(nowl+nowr)>>1;
    push_down(pos_now);
    if(l<=mid) update(l,r,lson,plus);
    if(r>mid) update(l,r,rson,plus);
    t[pos]=t[ls(pos)]+t[rs(pos)];
}
il SegMent_Tree query(int l,int r,int nowl,int nowr,int pos){
    if(l<=nowl&&r>=nowr){
        return t[pos];
    }
    int mid=(nowl+nowr)>>1;
    push_down(pos_now);
    SegMent_Tree temp;
    if(l<=mid) temp=temp+query(l,r,lson);
    if(r>mid) temp=temp+query(l,r,rson);
    return temp;
}
signed main(){
    ios::sync_with_stdio(0);
    cin>>n>>m;
    for(re int i=1;i<=n;i++) cin>>a[i];
    build(root);
    while(m--){
        cin>>opt;
        if(opt==1){
            cin>>x>>y>>k;
            update(x,y,root,k);
        }
        if(opt==2){
            cin>>x>>y;
            cout<<query(x,y,root).sum<<endl;
        }
    }
    return 0;
}

KMP:

il int KMP(const string& a,const string& b){
    int la=a.size(),lb=b.size(),i=0,j=-1,sum=0;
    if(la<lb) return 0;
    kmp[i]=-1;
    while(i<lb){
        if(j==-1||b[i]==b[j]) kmp[++i]=++j;
        else j=kmp[j];
    }
    j=i=0;
    while(i<la){
        if(j==-1||b[j]==a[i]) ++i,++j;
        else j=kmp[j];
        if(j==lb){
            sum++;
            j=kmp[j-1];
            i--;
        }
    }
    return sum;
}