【BZOJ2434】【NOI2011】Ari’s Typewriter (AC Automata and Properties of Fail Trees, Tree Array)

Description

Ali likes to collect all kinds of quirky things, and he recently found an old-fashioned typewriter. There are only 28 keys on the typewriter, which are printed with 26 lowercase English letters and two letters 'B' and 'P'.
According to Ali's research, this typewriter works like this:
- Enter a lowercase letter, and the letter will be added to one of the grooves of the typewriter (the letter is added at the end of the groove).
- Press the key marked 'B' once and the last letter in the groove of the typewriter will disappear.
- Press the key printed with 'P' and the typewriter will print all the existing letters in the groove on the paper and wrap, but the letters in the groove will not disappear.
For example, when Ali enters aPaPBbP, the characters printed on the paper are as follows:

a
aa
ab

We take the string printed on the paper from 1 Start sequential numbering, until n . The typewriter has a very interesting feature, a keypad with numbers is hidden in the typewriter, and two numbers are entered on the keypad. ( x , and ) (in 1 x , and n ), the typewriter displays the x The printed strings are in the and How many times in the printed string.
Ahri was very excited when he discovered this function. He wanted to write a program to accomplish the same function. Can you help him?


Solution

First of all, for the three operations given in the question, the corresponding ones on the Trie are:
- lowercase letter -> go to the child node of the letter of the current node (if not, create a new one).
- P -> mark an end
- B -> return to the parent node
We first build the AC automaton corresponding to the string given by the title according to the above rules.

failProperties of trees for AC automata :
if two strings in the automaton p , s satisfy p exist s appeared in k times, then k equal p FailHow many nodes in the subtree of the tree at the end of the string belong to the string s

With this property, we can first find the Failtree dfn.
For each inquiry, press and Sort, walk on the input string once, insert it into the tree array every time you go to a point , delete dfnit from the tree array every time you leave a point . dfnIf you go to ask and , we query how many points are in the tree array and then and dfnIt can be within the scope of the subtree of the corresponding node .


Code

/************************************************
 * Au: Hany01
 * Date: May 5th, 2018
 * Prob: [BZOJ2434][NOI2011] 阿狸的打字机
 * Email: [email protected]
************************************************/

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
#define File(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout)
#define rep(i, j) for (register int i = 0, i##_end_ = (j); i < i##_end_; ++ i)
#define For(i, j, k) for (register int i = (j), i##_end_ = (k); i <= i##_end_; ++ i)
#define Fordown(i, j, k) for (register int i = (j), i##_end_ = (k); i >= i##_end_; -- i)
#define Set(a, b) memset(a, b, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define x first
#define y second
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
#define ALL(a) (a).begin(), (a).end()
#define SZ(a) ((int)(a).size())
#define INF (0x3f3f3f3f)
#define INF1 (2139062143)
#define Mod (1000000007)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define y1 wozenmezhemecaia

template <typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
template <typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }

inline int read()
{
    register int _, __; register char c_;
    for (_ = 0, __ = 1, c_ = getchar(); c_ < '0' || c_ > '9'; c_ = getchar()) if (c_ == '-') __ = -1;
    for ( ; c_ >= '0' && c_ <= '9'; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);
    return _ * __;
}

////////////////////////Statement////////////////////////////
const int maxn = 100005;

int n, Ans[maxn], dfn[maxn], efn[maxn], tot, cnt, now, len, beg[maxn], nex[maxn], v[maxn], e, clk, pos[maxn];
char s[maxn];

//////////////////Aho-Corasick Automaton/////////////////////

struct Node
{
    int ch[26], fa, fail;
}t[maxn];

inline void buildTrie()
{
    static int u = 0;
    rep(i, len)
        if (s[i] == 'B') u = t[u].fa;
        else if (s[i] != 'P') {
            register int c = s[i] - 97;
            if (!t[u].ch[c]) t[u].ch[c] = ++ tot, t[tot].fa = u;
            u = t[u].ch[c];
        } else pos[++ cnt] = u;
    cnt = 0;
}

inline void getFail()
{
    static queue<int> q;
    rep(i, 26) if (t[0].ch[i]) q.push(t[0].ch[i]);
    while (!q.empty()) {
        register int u = q.front(), v, w; q.pop();
        rep(i, 26) if (v = t[u].ch[i]) {
            w = t[u].fail;
            while (w && !t[w].ch[i]) w = t[w].fail;
            t[v].fail = t[w].ch[i], q.push(v);
        }
    }
}

/////////////////////Build Tree//////////////////////////////

inline void add(int uu, int vv) { v[++ e] = vv, nex[e] = beg[uu], beg[uu] = e; }

void getdfn(int u)
{
    dfn[u] = ++ clk;
    for (register int i = beg[u]; i; i = nex[i]) getdfn(v[i]);
    efn[u] = clk;
}

////////////////////Answer Questions/////////////////////////

struct Question
{
    int p, s, id;
    bool operator < (const Question& A) const { return s < A.s; };
}Q[maxn];

struct FenwickTree
{
    int c[maxn];

#define lb(x) ((x) & -(x))

    inline void update(int x, int dt) {
        for ( ; x <= clk; x += lb(x)) c[x] += dt;
    }

    inline int query(int x) {
        register int Ans = 0;
        for ( ; x; x -= lb(x)) Ans += c[x];
        return Ans;
    }

    inline int query(int l, int r) { return query(r) - query(l - 1); }

}FT;

inline void Solve()
{
    static int u = 0;
    rep(i, len) {
        if (s[i] == 'B') FT.update(dfn[u], -1), u = t[u].fa;
        else if (s[i] == 'P') {
            ++ cnt;
            while (cnt == Q[now].s)
                Ans[Q[now].id] = FT.query(dfn[pos[Q[now].p]], efn[pos[Q[now].p]]), ++ now;
        } else u = t[u].ch[s[i] - 97], FT.update(dfn[u], 1);
    }
}

//////////////////////Main Function//////////////////////////

int main()
{
#ifdef hany01
    File("bzoj2434");
#endif

    scanf("%s", s), len = strlen(s);
    buildTrie(), getFail();

    For(i, 1, tot) add(t[i].fail, i);
    getdfn(0);

    n = read();
    For(i, 1, n) Q[i].p = read(), Q[i].s = read(), Q[i].id = i;
    sort(Q + 1, Q + 1 + n);

    now = 1, Solve();
    For(i, 1, n) printf("%d\n", Ans[i]);

    return 0;
}
//岭上逢久别者又别
//唐代 权德舆
//十年曾一别,征路此相逢。
//马首向何处?夕阳千万峰。 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325643787&siteId=291194637