zoukankan      html  css  js  c++  java
  • Codeforces 631D

    题目:http://codeforces.com/problemset/problem/631/D
    题意:
    输入一段压缩后的字符串,问子串在主串中出现的次数
    分析:
    KMP匹配求子串在主串中出现的次数,因为是压缩后的字符串,这就要考虑字符串的长度。因为要完全匹配,显然,模式串的中间的字符和数目必须要完全和主串匹配,但是前后两个字符数目可以不相等,所以模式串删去前后两个字符,去和主串匹配,完全匹配时,在比较前后两个字符是否主串中相应位置的字符匹配。删去前后两个字符前,要判断模式串长度:
    如果模式串长度是1,那么直接在主串中找对应的字符,比较长度,如果模式串长度是2,那么也是直接在主串中找模式串,比较字符一样,并且主串中字符数目均不小于模式串中字符数目。然后剩下的就用KMP匹配就好。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define fi first
    #define se second
    #define mp make_pair
    typedef long long ll;
    typedef pair<char,ll>pii;
    const int N=2e5+5;
    pii s[N],t[N],t0,tt;
    int next[N],tlen,slen;
    void getNext()
    {
        int i,j;
        i=0;j=next[0]=-1;
        while(i<tlen){
            if(j==-1||t[i]==t[j])next[++i]=++j;
            else j=next[j];
        }
    }
    ll KMP_Count()
    {
        ll ans=0;
        getNext();
        int j=0;
        for(int i=1;i<slen;i++){
            while(j>0&&s[i]!=t[j])j=next[j];
            if(s[i]==t[j])j++;
            if(j==tlen){
                if(t0.fi==s[i-tlen].fi&&t0.se<=s[i-tlen].se
                &&tt.fi==s[i+1].fi&&tt.se<=s[i+1].se)ans++;
                j=next[j];
            }
        }
        return ans;
    }
    int main()
    {
        int n,m;
        //freopen("f.txt","r",stdin);
        scanf("%d%d",&n,&m);
        char ci;
        ll li;
        scanf("%I64d-%c",&s[0].se,&s[0].fi);
        n--; slen=1;
        while(n--){
            scanf("%I64d-%c",&li,&ci);
            if(s[slen-1].fi==ci){
                s[slen-1].se+=li;
            }
            else s[slen++]=mp(ci,li);
        }
        scanf("%I64d-%c",&t[0].se,&t[0].fi);
        //cout<<t[0].fi<<' '<<t[0].se<<endl;
        m--; tlen=1;
        while(m--){
            scanf("%I64d-%c",&li,&ci);
            if(t[tlen-1].fi==ci){
                t[tlen-1].se+=li;
            }
            else t[tlen++]=mp(ci,li);
        }
        if(tlen==1){
            ll ans=0;
            for(int i=0;i<slen;i++){
                if(t[0].fi==s[i].fi&&t[0].se<=s[i].se)ans+=s[i].se-t[0].se+1;
            }
            cout<<ans<<endl;return 0;
        }
        if(tlen==2){
            ll ans=0;
            for(int i=1;i<slen;i++){
                if(t[0].fi==s[i-1].fi&&t[1].fi==s[i].fi
                   &&t[0].se<=s[i-1].se&&t[1].se<=s[i].se){
                    ans++;
                }
            }
            cout<<ans<<endl;return 0;
        }
        t0=t[0];tt=t[tlen-1];
        for(int i=0;i<tlen-1;i++)
            t[i]=t[i+1];
        tlen-=2;
        cout<<KMP_Count()<<endl;
        return 0;
    }
    

    Input

    The first line of the input contains two integers n and m (1 ≤ n, m ≤ 200 000) — the number of blocks in the strings t and s, respectively.

    The second line contains the descriptions of n parts of string t in the format “li-ci” (1 ≤ li ≤ 1 000 000) — the length of the i-th part and the corresponding lowercase English letter.

    The second line contains the descriptions of m parts of string s in the format “li-ci” (1 ≤ li ≤ 1 000 000) — the length of the i-th part and the corresponding lowercase English letter.
    Output

    Print a single integer — the number of occurrences of s in t.
    Examples
    Input

    5 3
    3-a 2-b 4-c 3-a 2-c
    2-a 2-b 1-c

    Output

    1

  • 相关阅读:
    算法学习概述(2016.6)
    java异常和错误类总结(2016.5)
    java string 细节原理分析(2016.5)
    MySQL 5.7.18 解压版安装
    Struts2的<s:date>标签使用详解[转]
    jprofile查看hprof文件[转]
    iBatis的Settings节点参数详解[转]
    window.open、window.showModalDialog和window.showModelessDialog 的区别[转]
    oracle 字典表查询
    oracle 表空间操作
  • 原文地址:https://www.cnblogs.com/01world/p/5651263.html
Copyright © 2011-2022 走看看