zoukankan      html  css  js  c++  java
  • CF631D Messenger(KMP)

    虽然是块,但是其实可以看作是除了两边的两块外,中间做一下kmp算法

    但是有几个坑点:

    1.相同的数字要合并,因为相同的数字代表的其实是同一种,如果不合并,在匹配的时候看上去是不一样的

    2.对于块数为1和2的直接特判一下就好

    3.对于中间匹配的,也不要忘记判断一下两边的块是否合理

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<ll,ll> pll;
    const int N=5e5+10;
    const int inf=0x3f3f3f3f;
    const ll mod=998244353;
    struct node{
        ll l;
        char c;
    }a[N],b[N];
    int n,m;
    int nxt[N];
    void get(node *a,int &n){
        int m=0;
        for(int i=0;i<n;++i)
        {
            if(m==0 || a[m-1].c!=a[i].c)
                a[m++]=a[i];
            else
                a[m-1].l+=a[i].l;
        }
        n=m;
    }
    void get_nxt(){
        nxt[1]=0;
        int i;
        int j;
        for(i=2,j=0;i<m-1;i++){
            while(j&&!(b[j+1].l==b[i].l&&b[j+1].c==b[i].c))
                j=nxt[j];
            if((b[j+1].l==b[i].l&&b[j+1].c==b[i].c))
                j++;
            nxt[i]=j;
        }
    }
    ll solve(){
        get_nxt();
        int i,j;
        ll ans=0;
        for(i=0,j=0;i<n;i++){
            while(j&&!((b[j+1].l==a[i].l&&b[j+1].c==a[i].c)))
                j=nxt[j];
            if(b[j+1].l==a[i].l&&b[j+1].c==a[i].c)
                j++;
            if(j==m-2){
                if(a[i+1].c==b[m-1].c&&a[i+1].l>=b[m-1].l&&a[i-m+2].c==b[0].c&&a[i-m+2].l>=b[0].l)
                    ans++;
                j=nxt[j];
            }
        }
        return ans;
    }
    int main(){
        //ios::sync_with_stdio(false);
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;++i)scanf("%lld-%c",&a[i].l,&a[i].c);
        for(int i=0;i<m;++i)scanf("%lld-%c",&b[i].l,&b[i].c);
        get(a,n);
        get(b,m);
        if(m==1){
            ll ans=0;
            int i;
            for(i=0;i<n;i++){
                if(a[i].c==b[0].c&&a[i].l>=b[0].l){
                    ans+=a[i].l-b[0].l+1;
                }
            }
            cout<<ans<<endl;
        }
        else if(m==2){
            ll ans=0;
            for(int i=0;i<n-1;i++){
                if(a[i].c==b[0].c&&a[i].l>=b[0].l&&a[i+1].c==b[1].c&&a[i+1].l>=b[1].l)
                    ans++;
            }
            cout<<ans<<endl;
        }
        else{
            cout<<solve()<<endl;
        }
        return 0;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    HDU1698(线段树入门题)
    POJ2528(离散化+线段树区间更新)
    POJ3630(Trie树)
    HDU1251(字典树)
    HDU1247(经典字典树)
    POJ2513(字典树+图的连通性判断)
    POJ1363
    UVa11624(逃离火焰问题)
    HDOJ1495(倒水BFS)
    poj3414Pots(倒水BFS)
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13592365.html
Copyright © 2011-2022 走看看