zoukankan      html  css  js  c++  java
  • bzoj 2434 阿狸的打字机

    题目传送门

      传送站I

      传送站II

    题目大意

      阿狸有一个打字机,它有3种键:

    1. 向缓冲区追加小写字母
    2. P:打印当前缓冲区(缓冲区不变)
    3. B:删除缓冲区中最后一个字符

      然后多次询问第$x$个被打印出来的串在第$y$个被打印出来的串中出现多少次。

      每次查询相当于询问串$x$的结束节点在fail树中的子树包含多少串$y$的点。

      又因为这些串的构造比较另类。所以考虑把询问离线,然后用树状数组维护子树中关键点的个数。

    Code

      1 /**
      2  * bzoj
      3  * Problem#2434
      4  * Accepted
      5  * Time: 620ms
      6  * Memory: 17792k
      7  */
      8 #include <algorithm>
      9 #include <iostream>
     10 #include <cstdlib>
     11 #include <cstdio>
     12 #include <vector>
     13 #include <queue>
     14 #include <stack>
     15 using namespace std;
     16 typedef bool boolean;
     17 
     18 const int N = 1e5 + 5;
     19 
     20 typedef class IndexedTree {
     21     public:
     22         int s;
     23         int ar[N];
     24 
     25         void add(int idx, int val) {
     26             for ( ; idx <= s; idx += (idx & (-idx)))
     27                 ar[idx] += val;
     28         }
     29 
     30         int getSum(int idx) {
     31             int rt = 0;
     32             for ( ; idx; idx -= (idx & (-idx)))
     33                 rt += ar[idx];
     34             return rt;
     35         }
     36 }IndexedTree;
     37 
     38 typedef class TrieNode {
     39     public:
     40         int in, out;
     41         TrieNode* ch[26];
     42         TrieNode* fail;
     43 }TrieNode;
     44 
     45 TrieNode pool[N];
     46 TrieNode *top = pool;
     47 
     48 TrieNode* newnode() {
     49     return ++top;
     50 }
     51 
     52 typedef class AhoCorasick {
     53     public:
     54         TrieNode *rt;
     55 
     56         AhoCorasick():rt(newnode()) {    }
     57 
     58         void travel(char* str, TrieNode** ts) {
     59             stack<TrieNode*> s;
     60             TrieNode* p;
     61             s.push(rt);
     62             for (int i = 0, c, cp = 0; str[i]; i++) {
     63                 if (str[i] == 'B')
     64                     s.pop();
     65                 else if (str[i] == 'P')
     66                     ts[++cp] = s.top();
     67                 else {
     68                     p = s.top(), c = str[i] - 'a';
     69                     if (!p->ch[c])
     70                         p->ch[c] = newnode();
     71                     s.push(p->ch[c]);
     72                 }
     73             }
     74         }
     75 
     76         void build(vector<int> *g) {
     77             queue<TrieNode*> que;
     78             que.push(rt);
     79             while (!que.empty()) {
     80                 TrieNode* p = que.front();
     81                 que.pop();
     82                 for (int i = 0; i < 26; i++) {
     83                     TrieNode *np = p->ch[i], *f = p->fail;
     84                     if (!np)    continue;
     85                     while (f && !f->ch[i])    f = f->fail;
     86                     if (!f)
     87                         np->fail = rt;
     88                     else
     89                         np->fail = f->ch[i];
     90                     que.push(np);
     91                 }
     92             }
     93             for (TrieNode* p = top; p != pool + 1; p--)
     94                 g[p->fail - pool].push_back(p - pool);
     95         }
     96 }AhoCorasick;
     97 
     98 typedef class Query {
     99     public:
    100         int x, y, id;
    101 
    102         boolean operator < (Query b) const {
    103             return y < b.y;
    104         }
    105 }Query;
    106 
    107 int m, cnt = 0;
    108 char str[N];
    109 int *res;
    110 Query *qs;
    111 TrieNode** ts;
    112 vector<int> g[N];
    113 IndexedTree it;
    114 AhoCorasick ac;
    115 
    116 inline void init() {
    117     gets(str);
    118     scanf("%d", &m);
    119     qs = new Query[(m + 1)];
    120     res = new int[(m + 1)];
    121     ts = new TrieNode*[(m + 1)];
    122     for (int i = 1; i <= m; i++) {
    123         scanf("%d%d", &qs[i].x, &qs[i].y);
    124         qs[i].id = i;
    125     }
    126 }
    127 
    128 void dfs(int p) {
    129     pool[p].in = ++cnt;
    130     for (int i = 0; i < (signed) g[p].size(); i++)
    131         dfs(g[p][i]);
    132     pool[p].out = cnt;
    133 }
    134 
    135 inline void solve() {
    136     ac.travel(str, ts);
    137     ac.build(g);
    138     it.s = (top - pool + 1);
    139     dfs(1);
    140     sort(qs + 1, qs + m + 1);
    141     stack<TrieNode*> s;
    142     s.push(ac.rt);
    143     for (int i = 0, cur = 0, cq = 1; cq <= m && str[i]; i++) {
    144         TrieNode *p = s.top();
    145         if (str[i] == 'B') {
    146             it.add(p->in, -1);
    147             s.pop();
    148         } else if (str[i] == 'P') {
    149             cur++;
    150             while (cq <= m && qs[cq].y == cur)
    151                 res[qs[cq].id] = it.getSum(ts[qs[cq].x]->out) - it.getSum(ts[qs[cq].x]->in - 1), cq++;
    152         } else {
    153             p = p->ch[str[i] - 'a'];
    154             it.add(p->in, 1);
    155             s.push(p);
    156         }
    157     }
    158     for (int i = 1; i <= m; i++)
    159         printf("%d
    ", res[i]);
    160 }
    161 
    162 int main() {
    163     init();
    164     solve();
    165     return 0;
    166 }
  • 相关阅读:
    城市社会经济专项规划之生态产业规划
    土地资源承载力研究
    生态功能区划方法之三:聚类分析法和生态融合法
    生态功能区划综述
    生态功能区划及生态规划的重要内容:生态环境现状评价
    生态功能区划方法之一:生态敏感性分析法
    生态环境专项规划
    城市社会经济专项规划之生态人居规划
    城市生态规划关键技术方法之五:生态支持系统瓶颈分析方法
    环境容量研究
  • 原文地址:https://www.cnblogs.com/yyf0309/p/8641293.html
Copyright © 2011-2022 走看看