zoukankan      html  css  js  c++  java
  • codevs 1946 阿狸的打字机

    题目描述 Description

    阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机 上只有 28 个按键,分别印有 26 个小写英文字母和'B'、'P'两个字母。 经阿狸研究发现,这个打字机是这样工作的:

     输入小写字母,打字机的一个凹槽中会加入这个字母(按 P 前凹槽中至 少有一个字母)。

     按一下印有'B'的按键,打字机凹槽中最后一个字母会消失。

     按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并 换行,但凹槽中的字母不会消失(保证凹槽中至少有一个字母)。

    例如,阿狸输入 aPaPBbP,纸上被打印的字符如下: a aa ab 我们把纸上打印出来的字符串从 1 开始顺序编号,一直到 n。打字机有一个 非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数 (x,y)(其中 1≤x,y≤n),打字机会显示第 x 个打印的字符串在第 y 个打印的字符串 中出现了多少次。 阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助 他么?

    输入描述 Input Description

    输入的第一行包含一个字符串,按阿狸的输入顺序给出所有阿狸输入的字符。 第二行包含一个整数 m,表示询问个数。 接下来 m 行描述所有由小键盘输入的询问。其中第 i 行包含两个整数 x, y, 表示第 i 个询问为(x, y)。

    输出描述 Output Description

    输出 m 行,其中第 i 行包含一个整数,表示第 i 个询问的答案。

    样例输入 Sample Input

    aPaPBbP

    3

    1 2

    1 3

    2 3

    样例输出 Sample Output

    2

    1

    0

    数据范围及提示 Data Size & Hint

    1≤n≤ 105,1≤m≤ 105

    很久以前就看到过的题。。大概是两年前,现在才把它写出来,想想自己这两年,有点唏嘘

    如果我们对这些串建一个AC自动机,我们会发现x在y中出现的次数就是fail树里面属于y这一字符串的结点个数

    然后发现输入正好每次只移动一个状态,那维护一下边移动便询问好了,按照fail边反向dfs一遍求出dfs序,用树状数组维护一下

      1 #include <iostream>
      2 #include <cstdlib>
      3 #include <cstdio>
      4 #include <algorithm>
      5 #include <string>
      6 #include <cstring>
      7 #include <cmath>
      8 #include <map>
      9 #include <stack>
     10 #include <set>
     11 #include <vector>
     12 #include <queue>
     13 #include <time.h>
     14 #define eps 1e-7
     15 #define INF 0x3f3f3f3f
     16 #define MOD 1000000007
     17 #define rep0(j,n) for(int j=0;j<n;++j)
     18 #define rep1(j,n) for(int j=1;j<=n;++j)
     19 #define pb push_back
     20 #define set0(n) memset(n,0,sizeof(n))
     21 #define ll long long
     22 #define ull unsigned long long
     23 #define iter(i,v) for(edge *i=head[v];i;i=i->next)
     24 #define max(a,b) (a>b?a:b)
     25 #define min(a,b) (a<b?a:b)
     26 #define lowbit(x) (x&-x)
     27 //#define OJ
     28 using namespace std;
     29 
     30 const int MAXINT = 100010;
     31 const int MAXNODE = 100010;
     32 const int MAXEDGE = 100010;
     33 int cnt_dfn, ans[MAXINT], m;
     34 char op[MAXINT];
     35 struct query {
     36     int x, y, id;
     37     query() {}
     38     query(int _x, int _y, int _id) :x(_x), y(_y), id(_id) {}
     39     bool operator < (const query &b) {
     40         return y < b.y;
     41     }
     42 } qr[MAXINT];
     43 struct fwt {
     44     int sum[MAXNODE], ub;
     45     void add(int p, int v) {
     46         while (p <= ub) {
     47             sum[p] += v;
     48             p += lowbit(p);
     49         }
     50     }
     51     int query(int p) {
     52         int ans = 0;
     53         while (p) {
     54             ans += sum[p];
     55             p -= lowbit(p);
     56         }
     57         return ans;
     58     }
     59 } fw;
     60 struct node {
     61     node *c[26], *fail, *pre;
     62     int dfn, max_dfn;
     63     vector<node*> eg;
     64 }*ed[MAXINT];
     65 struct ac_automaton {
     66     node mp[MAXNODE];
     67     node *q[MAXNODE];
     68     node *present, *root;
     69     int cnt;
     70     ac_automaton() {
     71         cnt = 0;
     72         present = root = new_node();
     73     }
     74     node *new_node() {
     75         return &mp[cnt++];
     76     }
     77     void back() {
     78         present = present->pre;
     79     }
     80     void add(char c) {
     81         int w = c - 'a';
     82         if (!present->c[w]) {
     83             present->c[w] = new_node();
     84             present->c[w]->pre = present;
     85         }
     86         present = present->c[w];
     87         //present->cnt++;
     88     }
     89     void get_fail() {
     90         int h = 0, t = 0;
     91         node *p, *tp;
     92         root->fail = NULL;
     93         q[t++] = root;
     94         while (h != t) {
     95             p = q[h++];
     96             rep0(i, 26) {
     97                 if (p->c[i]) {
     98                     if (p == root) p->c[i]->fail = root;
     99                     else {
    100                         tp = p->fail;
    101                         while (tp) {
    102                             if (tp->c[i]) {
    103                                 p->c[i]->fail = tp->c[i];
    104                                 break;
    105                             }
    106                             tp = tp->fail;
    107                         }
    108                         if (!tp) p->c[i]->fail = root;
    109                     }
    110                     q[t++] = p->c[i];
    111                 }
    112             }
    113         }
    114     }
    115     void link_edge() {
    116         rep0(i, cnt) {
    117             if (mp[i].fail) {
    118                 mp[i].fail->eg.push_back(&mp[i]);
    119             }
    120         }
    121     }
    122     void dfs(node* p) {
    123         p->dfn = ++cnt_dfn;
    124         for (vector<node*>::iterator i = p->eg.begin(); i != p->eg.end(); ++i) {
    125             dfs(*i);
    126         }
    127         p->max_dfn = cnt_dfn;
    128     }
    129 } acm;
    130 int read() {
    131     char c = getchar(); int f = 1, x = 0;
    132     while (!isdigit(c)) { if (c == '-') f = -1; c = getchar(); }
    133     while (isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); }
    134     return f * x;
    135 }
    136 char get_ch() {
    137     char c = getchar();
    138     while (!isalpha(c)) c = getchar();
    139     return c;
    140 }
    141 void get_input();
    142 void work();
    143 int main() {
    144     freopen("in.txt", "r", stdin);
    145     get_input();
    146     work();
    147     return 0;
    148 }
    149 void work() {
    150     int s_cnt = 0, j = 0;
    151     sort(qr, qr + m);
    152     fw.ub = MAXINT;
    153     int l = strlen(op);
    154     rep0(i, l) {
    155         if (op[i] == 'B') {
    156             acm.back();
    157             continue;
    158         }
    159         if (op[i] == 'P') {
    160             s_cnt++;
    161             ed[s_cnt] = acm.present;
    162             continue;
    163         }
    164         acm.add(op[i]);
    165     }
    166     s_cnt = 0;
    167     acm.get_fail();
    168     acm.link_edge();
    169     acm.dfs(acm.root);
    170     acm.present = acm.root;
    171     rep0(i, l) {
    172         if (op[i] == 'B') {
    173             fw.add(acm.present->dfn, -1);
    174             acm.back();
    175             continue;
    176         }
    177         if (op[i] == 'P') {
    178             s_cnt++;
    179             for (; s_cnt == qr[j].y; j++) {
    180                 ans[qr[j].id] = fw.query(ed[qr[j].x]->max_dfn) - fw.query(ed[qr[j].x]->dfn - 1);
    181             }
    182             continue;
    183         }
    184         acm.add(op[i]);
    185         fw.add(acm.present->dfn, 1);
    186     }
    187     rep0(i, m) printf("%d
    ", ans[i]);
    188 }
    189 void get_input() {
    190     scanf("%s", op);
    191     m = read();
    192     rep0(i, m) {
    193         qr[i].x = read();
    194         qr[i].y = read();
    195         qr[i].id = i;
    196     }
    197 }
    许愿弥生改二
  • 相关阅读:
    .net 存储过程中的 output参数取值问题
    【从零开始学Servlet笔记】Servelet入门
    【从零开始学Servlet笔记】Web资源
    【从零开始学Servlet笔记】Http协议
    【从零开始学Mybatis笔记】SqlMapConfig.xml配置文件
    【从零开始学Mybatis笔记】Dao开发方法
    【从零开始学Mybatis笔记】Mybatis入门
    【从零开始学SpringMVC笔记】SpringMVC进阶
    【从零开始学SpringMVC笔记】SpringMVC与struts2不同
    【从零开始学SpringMVC笔记】参数绑定
  • 原文地址:https://www.cnblogs.com/LoveYayoi/p/6745416.html
Copyright © 2011-2022 走看看