@loj - 2507 @ 「CEOI2011」 Matching


@description@

For the sequence of integers \ ((a_1, a_2, ... , a_n) \) and from 1 to n are arranged \ ((P_1, P_2, ..., P_n) \) , called \ ((a_1, a_2, .. ., a_n) \) in line with \ ((p_1, P_2, ..., P_n) \) , if and only if:

(1) {a} of any two numbers differ from each other.
(2) \ ((a_1, a_2, ... , a_n) \) after ascending order, will be \ ((a_ {p_1}, a_ {p_2}, ..., a_ {p_n}) \) .

1 ~ n will now be given of the arrangement of the sequence {p} \ (H_1, H_2, ..., h_m \) , you determine which substring h are arranged in line with {p}.

Input format
of the first row of the two spaces separated by a positive integer n, m.
The second row of n positive integers separated by a space, shows an arrangement p.
The third row space separated positive integer number m, a sequence h.

Output format
of the first line of an integer k, denotes the number of sub-strings of compliance {p}.
The second row of space apart a positive integer k, represents the substring starting position (numbering starting from 1). The position of the output set in ascending order. In particular, if k = 0, then you should also outputs a blank line.

Sample input
. 5 10
2. 4. 3. 1. 5
. 5. 6. 8. 3. 1. 7 10. 11. 9 12 is
sample output
2
2. 6

And prompt data range
2 <= n <= m < = 1000000; 1 <= hi <= 10 ^ 9; 1 <= pi <= n.
And to ensure that {h} mutually different elements, {p} is a permutation.

@solution@

First step conversion problems as: find {q} such that \ (Q_ P_i} = {I \) , i.e., {p} is the inverse permutation.
Then a substring meet {p} may be equivalent to the substring after discretization 1 ~ n is equal to q.

If you do not consider discrete, then that is a classic sub-string matching problem, directly on the kmp.
If the substring determination method as isomorphic, that is, after discrete homogeneous, whether it can be extended kmp it?

When considering the need kmp isomorphic sentence: string with a known string at t s homogeneous, add s to the end of a a, a b add at the end of t, s + a is determined and if t + b isomorphic.
Because s and t have the same configuration, only after a and b can be added into the structure remains the same.
May be equivalent to a rank determined in s (s is smaller than a number) = b ranking (smaller than the number of t b) in the t.

Search rankings can be balanced tree, but this question directly to an array of discrete + tree.
Note kmp jump fail when the need to move a elements, because to maintain Fenwick tree.
But the complexity of the proof is not going to change. kmp or O (n), the set of a tree array is O (nlogn) a.

@accepted code@

#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int MAXN = 1000000;
int n, m;
int t[2][MAXN + 5];
int lowbit(int x) {return x & -x;}
void update(int x, int k, int type) {
    for(int i=x;i<=m;i+=lowbit(i))
        t[type][i] += k;
}
int sum(int x, int type) {
    int ret = 0;
    for(int i=x;i;i-=lowbit(i))
        ret += t[type][i];
    return ret;
}
int d[MAXN + 5], p[MAXN + 5], h[MAXN + 5];
void discrete() {
    for(int i=1;i<=m;i++) d[i] = h[i];
    sort(d + 1, d + m + 1);
    for(int i=1;i<=m;i++)
        h[i] = lower_bound(d + 1, d + m + 1, h[i]) - d;
}
int f[MAXN + 5];
void get_f() {
    f[1] = 0;
    int ri = 0, le = 2;
    for(int i=2;i<=n;i++) {
        int j = f[i-1];
        while( sum(p[j+1], 0) != sum(p[i], 1) ) {
            while( ri != f[j] )
                update(p[ri--], -1, 0), update(p[le++], -1, 1);
            j = f[j];
        }
        f[i] = j + 1;
        update(p[++ri], 1, 0), update(p[i], 1, 1);
    }
}
vector<int>ans;
void get_ans() {
    for(int i=1;i<=m;i++)
        t[0][i] = t[1][i] = 0;
    int le = 1, ri = 0, j = 0;
    for(int i=1;i<=m;i++) {
        while( sum(p[j+1], 0) != sum(h[i], 1) ) {
            while( ri != f[j] )
                update(p[ri--], -1, 0), update(h[le++], -1, 1);
            j = f[j];
        }
        j++;
        update(p[++ri], 1, 0), update(h[i], 1, 1);
        if( j == n ) {
            ans.push_back(i-n+1);
            while( ri != f[j] )
                update(p[ri--], -1, 0), update(h[le++], -1, 1);
            j = f[j];
        }
    }
}
int main() {
    scanf("%d%d", &n, &m);
    for(int i=1;i<=n;i++) {
        int x; scanf("%d", &x);
        p[x] = i;
    }
    for(int i=1;i<=m;i++) scanf("%d", &h[i]);
    discrete(), get_f(), get_ans();
    printf("%d\n", (int)ans.size());
    for(int i=0;i<(int)ans.size();i++)
        printf("%d%c", ans[i], (i + 1 == ans.size() ? '\n' : ' '));
    if( ans.empty() ) puts("");
}

@details@

I have thought about the string hash, hash because this is directly Cantor launched count.
This problem can not be found hash prefix and subtraction, dynamic maintenance feel even write a balanced tree, then gave up.
After all, with respect to the balance we still prefer the code tree brief Fenwick tree bar.

Guess you like

Origin www.cnblogs.com/Tiw-Air-OAO/p/11845570.html