zoukankan      html  css  js  c++  java
  • 匹配

    题目描述

    Chino和Kokoa想好了装饰方案,装饰方案为一个长为m的数列。此外,她们还有一个模板方案,为一个长为n的数列。两个数列A,B匹配的定义为:匹配的定义改为:存在一个字符的映射,使得A应用这个映射之后等于B,且这个映射必须为一个排列。
         A=121,B=313,当映射为{1→3,2→1,3→2}时A′=B,可以匹配。
    A=212,B=313,当映射为{1→1,2→3,3→2}时A′=B,可以匹配。
    A=232,B=313,当映射为{1→2,2→3,3→1}时A′=B,可以匹配。
    A=123,B=111,当映射为{1→1,2→1,3→1}时A′=B,但此时映射不为一个排列,不能匹配。
    Chino想知道模板序列有哪些连续子序列和她们想的序列匹配。

    输入

    第一行两个数t和c   t为数据组数,c为字符集大小
    每组数据:
    第一行两个数n,m
    第二行n个数表示模板序列
    第三行m个数表示装饰序列

    输出

    每组数据第一行一个数表示该组数据答案个数
    第二行若干个数表示合法序列的开头位置(升序)

    样例输入

    3 3
    6 3
    1 2 1 2 3 2
    3 1 3
    6 3
    1 2 1 2 1 2
    3 1 3
    6 3
    1 1 2 1 2 1
    3 1 3
    

    样例输出

    3
    1 2 4
    4
    1 2 3 4
    3
    2 3 4
    

    提示

    数据范围:

    10% n,m,c<=1e3

    另外20% n,m<=1e5 c<=40

    另外30% n,m,c,<=1e5

    100% n,m,c<=1e6,t<=3
     
    考虑对一个序列进行hash,每个位置i的值可以定义为i-这个元素上一次出现的位置。
    如果是首次出现,那么就是0。这个东西显然可以递推。
    #include <bits/stdc++.h>
    using namespace std;
    #define M 1000010
    #define MOD 1000000007
    int n, m, C;
    int head[M], Ne[M], fr[M];
    int P[M];
    int a[M], b[M];     
    vector<int> V;
    inline void solve(int H) {
        V.clear();
        memset(head, 0, sizeof(head));
        memset(fr, 0, sizeof(fr));
        memset(Ne, 0, sizeof(Ne));
        for(int i = n; i >= 1; -- i) {
            fr[head[a[i]]] = i;
            Ne[i] = head[a[i]];
            head[a[i]] = i;
        }
        int wt = 0;
        for(int i = 1; i <= m; ++ i) {
            if(fr[i] == 0) {
                wt = (1ll * wt * 1000003) % MOD;
            }
            else wt = (1ll * wt * 1000003 + (i - fr[i])) % MOD;
        }
        if(wt == H) V.push_back(1);
        for(int i = 2; i <= n - m + 1; ++ i) {
            wt = 1ll * wt * 1000003 % MOD;
            int N = i + m - 1;
            if(Ne[i - 1] < N && Ne[i - 1]) wt -= (1ll * (Ne[i - 1] - (i - 1)) * P[N - Ne[i - 1]] % MOD);
            if(wt < 0) wt += MOD;
            if(fr[N] >= i) {
                wt += N - fr[N];
                if(wt >= MOD) wt -= MOD;
            }
            if(wt == H) V.push_back(i);
        }
    }
    int main() {
        int T;
        scanf("%d%d", &T, &C);
        P[0] = 1;
        for(int i = 1; i <= 1000000; ++ i) {
            P[i] = 1ll * P[i - 1] * 1000003 % MOD;
        }
        while(T --) {
            scanf("%d%d", &n, &m);
            for(int i = 1; i <= n; ++ i) scanf("%d", &a[i]);
            for(int i = 1; i <= m; ++ i) scanf("%d", &b[i]);
            memset(head, 0, sizeof(head));
            memset(fr, 0, sizeof(fr));
            for(int i = m; i >= 1; -- i) {
                fr[head[b[i]]] = i;
                head[b[i]] = i;
            }
            int H = 0;
            for(int i = 1; i <= m; ++ i) {
                if(fr[i] == 0) {
                    H = (1ll * H * 1000003) % MOD;
                }
                else H = (1ll * H * 1000003 + (i - fr[i])) % MOD;
            }
            solve(H);
            printf("%d
    ", V.size());
            for(int i = 0; i < V.size(); ++ i) {
                printf("%d ", V[i]);
            }
            puts("");
        }
    }
  • 相关阅读:
    BOZJ 3551&BZOJ 3545 kruskal重构树
    [Poi2014]FarmCraft
    NOIP 2015 斗地主
    POJ 1704 Georgia and Bob
    BZOJ 1409 快速幂+欧拉定理
    最长公共子序列(LCS)
    神奇的口袋(百练2755)
    最长上升子序列(LIS)
    《Single Image Haze Removal Using Dark Channel Prior》去雾代码实现分析
    MATLAB中的nargin与varargin
  • 原文地址:https://www.cnblogs.com/iamqzh233/p/9427651.html
Copyright © 2011-2022 走看看