zoukankan      html  css  js  c++  java
  • 【TJOI2013】单词

    Description

    给定若干模式串组成的文本串,求每个模式串出现的次数。

    Solution

    由于模式串可能重复,所以直接按照AC自动机的模板会出错,所以我们定义一个same数组,end数组只记录最早的编号,每次如果要覆盖,便把令该节点的same值为这个位置上的end的值,查询一遍,输出答案就输出ans[same[i]]。

    我们再定义两个数组vis和sum表示当前节点有没有被扫过,当前节点被覆盖的次数。那么在统计答案的时候,如果当前节点是某个模式串的结尾并且没有扫过,那么说明这个模式串有贡献,就将答案+sum[now],之后将vis赋值为1,这样跑一边AC自动机就可以了。

    Code

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int n, tot, same[100010], ans[100010], ch[500010][26], end[500010], vis[500010], sum[500010];
     4 int f[500010];
     5 char c[210][100010];
     6 inline int read() {
     7     int ret = 0, op = 1;
     8     char c = getchar();
     9     while (!isdigit(c)) {
    10         if (c == '-') op = -1; 
    11         c = getchar();
    12     }
    13     while (isdigit(c)) {
    14         ret = ret * 10 + c - '0';
    15         c = getchar();
    16     }
    17     return ret * op;
    18 }
    19 inline void write(int x) {
    20     if (x < 0) putchar('-'), x = -x;
    21     if (x >= 10) write(x / 10);
    22     putchar(x % 10 + '0');
    23 }
    24 void insert(char *a, int id) {
    25     int now = 0, l = strlen(a);
    26     for (int i = 0; i < l; ++i) {
    27         if (!ch[now][a[i] - 'a']) ch[now][a[i] - 'a'] = ++tot;
    28         now = ch[now][a[i] - 'a'];
    29         sum[now]++;
    30     }
    31     if (!end[now]) end[now] = id;
    32     else same[id] = end[now];
    33 }
    34 queue <int> q;
    35 void bfs() {
    36     for (register int i = 0; i < 26; ++i)
    37         if (ch[0][i]) {
    38             f[ch[0][i]] = 0;
    39             q.push(ch[0][i]);
    40         }
    41     while (!q.empty()) {
    42         int now = q.front();
    43         q.pop();
    44         for (register int i = 0; i < 26; ++i) {
    45             if (ch[now][i]) f[ch[now][i]] = ch[f[now]][i], q.push(ch[now][i]);
    46             else ch[now][i] = ch[f[now]][i];
    47         }
    48     }
    49 }
    50 void query(char *a) {
    51     int now = 0;
    52     int l = strlen(a);
    53     for (int i = 0; i < l; ++i) {
    54         now = ch[now][a[i] - 'a'];
    55         for (register int j = now; j; j = f[j])
    56             if (end[j] && !vis[now]) ans[end[j]] += sum[now];
    57         vis[now] = 1;
    58     }
    59 }
    60 int main() {
    61     n = read();
    62     for (register int i = 1; i <= n; ++i) {
    63         scanf("%s", c[i]);
    64         insert(c[i], i);
    65     }
    66     bfs();
    67     for (register int i = 1; i <= n; ++i) 
    68         if (!same[i]) query(c[i]);
    69     for (register int i = 1; i <= n; ++i) {
    70         if (!same[i]) write(ans[i]);
    71         else write(ans[same[i]]);
    72         puts("");
    73     }
    74     return 0;
    75 }
    AC Code
  • 相关阅读:
    实现windows数据更新
    使用ListView展示数据
    构建良好的windous布局
    初始Windows系统
    用C#连接SQL sever数据库
    分组查询与内外连接查询
    SQL Server中数据查询基础
    使用SQL语句操作数据
    CHECK约束表达式
    聊聊四种冷启动,和它们的成本、竞争门槛
  • 原文地址:https://www.cnblogs.com/shl-blog/p/11262780.html
Copyright © 2011-2022 走看看