zoukankan      html  css  js  c++  java
  • hdu5384(trie树)

    hdu5384

    给定n个字符串Ai

    给定m个字符串Bi

    问所有的Bi在每个Ai中出现了多少次

    很显然,对Bi建Trie图,然后每次用Ai去匹配的时候,不断查找当前匹配串的最长后缀,这样就能找到答案了

    比赛的时候也这样水过了。(又一次我认为这样不会过,但是交上去却过了)

    如有有这样的数据的话

    1

    1 1

    10^5个a

    10^5个a

    那么时间复杂度是10^10,

    其实上面不断查找当前匹配串的最长后缀是没必要的,是重复操作的。

    如果我们知道当前匹配串的最长后缀包含了多少个Bi,那么就不用去不断回溯了。

    所以我们只要在构建fail指针的时候,处理处当前fail指针指向的字符串包含了多少个Bi,那么就不用不断的回溯了。

    (哈哈,学到东西了)

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <stdlib.h>
      4 #include <algorithm>
      5 #include <iostream>
      6 #include <queue>
      7 #include <stack>
      8 #include <vector>
      9 #include <map>
     10 #include <set>
     11 #include <string>
     12 #include <math.h>
     13 using namespace std;
     14 #pragma warning(disable:4996)
     15 #pragma comment(linker, "/STACK:1024000000,1024000000")
     16 typedef long long LL;                   
     17 const int INF = 1<<30;
     18 /*
     19 
     20 */
     21 const int N = 1000000 + 10;
     22 struct Node
     23 {
     24     int fail, next[26];
     25     int cnt;
     26     void init()
     27     {
     28         fail = -1;
     29         cnt = 0;
     30         for (int i = 0; i < 26; ++i)
     31             next[i] = -1;
     32     }
     33 }Trie[N];
     34 int size;
     35 void insert(int root, char *str)
     36 {
     37     int idx, cur = root;
     38     for (int i = 0; str[i]; ++i)
     39     {
     40         idx = str[i] - 'a';
     41         if (Trie[cur].next[idx] == -1)
     42         {
     43             Trie[size].init();
     44             Trie[cur].next[idx] = size++;
     45         }
     46         cur = Trie[cur].next[idx];
     47     }
     48     Trie[cur].cnt++;
     49 }
     50 void makeFail(int root)
     51 {
     52     queue<int> q;
     53     for (int i = 0; i < 26; ++i)
     54     {
     55         if (Trie[root].next[i] == -1)
     56             Trie[root].next[i] = root;
     57         else
     58         {
     59             Trie[Trie[root].next[i]].fail = root;
     60             q.push(Trie[root].next[i]);
     61         }
     62     }
     63     while (!q.empty())
     64     {
     65         int cur = q.front();
     66         q.pop();
     67         for (int i = 0; i < 26; ++i)
     68         {
     69             if (Trie[cur].next[i] == -1)
     70             {
     71                 Trie[cur].next[i] = Trie[Trie[cur].fail].next[i];
     72             }
     73             else
     74             {
     75                 Trie[Trie[cur].next[i]].fail = Trie[Trie[cur].fail].next[i];
     76                 //处理处,当前fail指针指向的字符串包含了多少个Bi
     77                 Trie[Trie[cur].next[i]].cnt += Trie[Trie[Trie[cur].fail].next[i]].cnt;
     78                 q.push(Trie[cur].next[i]);
     79             }
     80 
     81         }
     82     }
     83 }
     84 int match(int root, char *str)
     85 {
     86     int i = 0;
     87     int idx;
     88     int cur = root;
     89     int ret = 0;
     90     while (str[i])
     91     {
     92         idx = str[i] - 'a';
     93         cur = Trie[cur].next[idx];
     94         //int tmp = cur;
     95         //while (tmp != root)
     96         //{
     97         //    ret += Trie[tmp].cnt;
     98         //    tmp = Trie[tmp].fail;
     99         //}
    100         
    101         ret += Trie[cur].cnt;
    102         i++;
    103     }
    104     return ret;
    105 }
    106 /*
    107 题目问所有的Bi在每一个Ai中出现的次数
    108 
    109 一个串的所有子串可以表示为它所有前缀的后缀
    110 对所有的Bi建trie图
    111 我们可以让每个Ai匹配的时候,就让这个当前字符串不断的去寻找最长后缀,
    112 时间复杂度吵了
    113 ,然而数据水,居然过了
    114 */
    115 
    116 char str[666666];
    117 char str2[666666];
    118 int main()
    119 {
    120     int t, n, m;
    121     //freopen("d:/in.txt", "r", stdin);
    122     scanf("%d", &t);
    123     while (t--)
    124     {
    125         scanf("%d%d", &n, &m);
    126         int idx = 0;
    127         size = 1;
    128         Trie[0].init();
    129         Trie[0].fail = 0;
    130         for (int i = 0; i < n; ++i)
    131         {
    132             scanf("%s", str + idx);
    133             idx += strlen(str + idx) + 1;
    134         }
    135         for (int i = 0; i < m; ++i)
    136         {
    137             scanf("%s", str2);
    138             insert(0,str2);
    139         }
    140         makeFail(0);
    141         idx = 0;
    142         for (int i = 0; i < n; ++i)
    143         {
    144             printf("%d
    ", match(0, str + idx));
    145             idx += strlen(str + idx) + 1;
    146         }
    147     }
    148     return 0;
    149 }
    View Code
  • 相关阅读:
    关闭浏览器清除cookie
    JSONP跨域请求数据报错 “Unexpected token :”的解决办法
    HTTP请求方法
    Html 中判断某个class的个数
    将div标签中的table水平居中
    js阻止事件冒泡
    Vue中V-bind的使用。为何标签中style="height:90px"也需要写为V-bind:style="height:90px",哪些属性需要绑定?哪些属性不需要绑定?
    css中 !important的作用。
    Notification通知
    DataAdapter中DeleteCommand和UpdateCommand
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4728613.html
Copyright © 2011-2022 走看看