zoukankan      html  css  js  c++  java
  • codeforces 631D. Messenger kmp

    题目链接

    首先想到kmp, 和普通的不一样的是,中间部分严格相等, 头和尾的字符相等但是数量可以不相等。 所以应该把子串的头和尾先去掉,然后对剩下的部分进行kmp。

    子串长度为1或2要特别讨论。

    不要忘记一开始先把相邻的相同的部分合并掉。

    #include <iostream>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #include <set>
    #include <string>
    #include <queue>
    #include <stack>
    #include <bitset>
    using namespace std;
    #define pb(x) push_back(x)
    #define ll long long
    #define mk(x, y) make_pair(x, y)
    #define lson l, m, rt<<1
    #define mem(a) memset(a, 0, sizeof(a))
    #define rson m+1, r, rt<<1|1
    #define mem1(a) memset(a, -1, sizeof(a))
    #define mem2(a) memset(a, 0x3f, sizeof(a))
    #define rep(i, n, a) for(int i = a; i<n; i++)
    #define fi first
    #define se second
    typedef pair<int, int> pll;
    const double PI = acos(-1.0);
    const double eps = 1e-8;
    const int mod = 1e9+7;
    const int inf = 1061109567;
    const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
    const int maxn = 2e5+5;
    pair <ll, char> a[maxn], b[maxn];
    #define next nextt
    int n, m, next[maxn];
    void init_kmp() {
        int i = 0, j = -1;
        next[0] = -1;
        while(i<m) {
            if(j == -1 || b[i] == b[j]) {
                ++i, ++j;
                next[i] = j;
            } else {
                j = next[j];
            }
        }
    }
    int main()
    {
        int x;
        char ch;
        cin>>n>>m;
        for(int i = 0; i<n; i++) {
            scanf("%I64d-%c", &x, &ch);
            a[i] = mk(x, ch);
        }
        for(int i = 0; i<m; i++) {
            scanf("%I64d-%c", &x, &ch);
            b[i] = mk(x, ch);
        }
        int cnt = 0;
        for(int i = 0; i<n-1; i++) {
            if(a[i].se == a[i+1].se) {
                a[cnt].fi += a[i+1].fi;
                continue;
            }
            a[++cnt] = a[i+1];
        }
        n = cnt+1;
        cnt = 0;
        for(int i = 0; i<m-1; i++) {
            if(b[i].se == b[i+1].se) {
                b[cnt].fi += b[i+1].fi;
                continue;
            }
            b[++cnt] = b[i+1];
        }
        m = cnt+1;
        ll ans = 0;
        if(m == 1) {
            for(int i = 0; i<n; i++) {
                if(a[i].se == b[0].se&&a[i].fi>=b[0].fi) {
                    ans += (a[i].fi-b[0].fi+1);
                }
            }
            cout<<ans<<endl;
            return 0;
        }
        if(m == 2) {
            for(int i = 0; i<n-1; i++) {
                if(a[i].se == b[0].se && a[i+1].se == b[1].se && a[i].fi>=b[0].fi&&a[i+1].fi>=b[1].fi) {
                    ans ++;
                }
            }
            cout<<ans<<endl;
            return 0;
        }
        pair <ll, char> s, e;
        s = b[0], e = b[m-1];
        cnt = 0;
        for(int i = 1; i<m-1; i++) {
            b[cnt++] = b[i];           //去掉头尾
        }
        m -= 2;
        init_kmp();
        int i = 1, j = 0;
        while(i<n-1) {
            if(j == -1 || a[i] == b[j]) {
                i++, j++;
            } else {
                j = next[j];
            }
            if(j == m) {
                if(s.se == a[i-j-1].se && s.fi<=a[i-j-1].fi
                   && a[i].se == e.se && a[i].fi>=e.fi) {
                        ans++;
                }
                j = next[j];
            }
        }
        cout<<ans<<endl;
        return 0;
    }
        
  • 相关阅读:
    算法导论
    深度探索C++对象模型
    git 介绍及其使用总结
    前端跨域常见的几种方式
    前端面试angular 常问问题总结
    低版本浏览器支持HTML5标签的方法
    理解 angular 的路由功能
    Angular 新手容易碰到的坑
    Angular 新手容易碰到的坑
    一 Unicode和UTF-8的异同
  • 原文地址:https://www.cnblogs.com/yohaha/p/5256417.html
Copyright © 2011-2022 走看看