• hdu3695 AC自动机优化


    题目链接:http://icpc.njust.edu.cn/Problem/Hdu/3695/

    不加last指针的AC自动机会T,原因是他费了很多功夫在跳转上,而last指针是直接直到跳转的终止位置,直接跳转到终止位置上,所以只有一次跳转。未优化的fail指针最坏的情况下复杂度是O(|S|*|T|),其中|S|是模式串长度的均值,|T|是文本串的 长度。

    代码如下:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define LL long long
      4 #define ULL unsigned LL
      5 #define fi first
      6 #define se second
      7 #define lson l,m,rt<<1
      8 #define rson m+1,r,rt<<1|1
      9 #define max3(a,b,c) max(a,max(b,c))
     10 #define min3(a,b,c) min(a,min(b,c))
     11 const int INF = 0x3f3f3f3f;
     12 const LL mod = 1e9+7;
     13 typedef pair<int,int> pll;
     14 const int N = 1e6+10;
     15 int tot = 2;
     16 char str[N*26], tmp[N*26];
     17 int trie[N*4][26], cnt[N*26], fair[N*26];
     18 void init(){
     19     for(int i = 1; i < tot; i++){
     20         for(int j = 0; j < 26; j++)
     21             trie[i][j] = 0;
     22     }
     23     tot = 2;
     24 }
     25 void Insert(){
     26     int rt = 1, len = strlen(str);
     27     for(int i = 0; i < len; i++){
     28         int id = str[i] - 'A';
     29         if(!trie[rt][id]) {
     30             cnt[tot] = 0;
     31             fair[tot] = 0;
     32             trie[rt][id] = tot++;
     33         }
     34         rt = trie[rt][id];
     35     }
     36     cnt[rt]++;
     37 }
     38 void Build_tree(){
     39     queue<int> q;
     40     q.push(1);
     41     int p;
     42     while(!q.empty()){
     43         int tmp = q.front();
     44         q.pop();
     45         for(int j = 0; j < 26; j++){
     46             if(trie[tmp][j]){
     47                 if(tmp == 1)
     48                     fair[trie[tmp][j]] = 1;
     49                 else {
     50                     p = fair[tmp];
     51                     while(p){
     52                         if(trie[p][j]){
     53                             fair[trie[tmp][j]] = trie[p][j];
     54                             break;
     55                         }
     56                         else p = fair[p];
     57                     }
     58                     if(!p) fair[trie[tmp][j]] = 1;
     59                 }
     60                 q.push(trie[tmp][j]);
     61             }
     62         }
     63     }
     64 }
     65 int Find(int len){
     66     int ret = 0, rt = 1;
     67     for(int i = 0; i < len; i++){
     68         int id = str[i] - 'A';
     69         while(rt !=  1 && !trie[rt][id]) rt = fair[rt];;
     70         if(trie[rt][id]) rt = trie[rt][id];
     71         int p = rt;
     72         while(p != 1){
     73             if(cnt[p] >= 0){
     74                 ret += cnt[p];
     75                 cnt[p] = -1;
     76             }
     77             else break;
     78             p = fair[p];
     79         }
     80     }
     81     rt = 1;
     82     for(int i = len - 1; i >= 0; i--){
     83         int id = str[i] - 'A';
     84         while(rt !=  1 && !trie[rt][id]) rt = fair[rt];
     85         if(trie[rt][id]) rt = trie[rt][id];
     86         int p = rt;
     87         while(p != 1){
     88             if(cnt[p] >= 0){
     89                 ret += cnt[p];
     90                 cnt[p] = -1;
     91             }
     92             else break;
     93             p = fair[p];
     94         }
     95     }
     96     return ret;
     97 }
     98 int main(){
     99     int t;
    100     scanf("%d", &t);
    101     while(t--){
    102         int n;
    103         init();
    104         scanf("%d", &n);
    105         while(n--){
    106             scanf("%s", str);
    107             Insert();
    108         }
    109         Build_tree();
    110         scanf("%s", tmp);
    111         int len = strlen(tmp);
    112         int ccc = 0;
    113         for(int i = 0; i < len; i++){
    114             if(tmp[i] != '['){
    115                 str[ccc++] = tmp[i];
    116             }
    117             else {
    118                 int _c = 0;
    119                 i++;
    120                 while(isdigit(tmp[i]))
    121                     _c = _c *10 + (int)(tmp[i]-'0'), i++;
    122                 while(_c--)
    123                     str[ccc++] = tmp[i];
    124                 i++;
    125             }
    126         }
    127         printf("%d
    ", Find(ccc));
    128     }
    129     return 0;
    130 }
  • 相关阅读:
    VUE学习一,安装及Hello World
    609. 在系统中查找重复文件
    451. 根据字符出现频率排序
    面试题 10.02. 变位词组
    142. 环形链表 II
    面试题 16.24. 数对和
    151. 翻转字符串里的单词
    1207. 独一无二的出现次数
    80. 删除排序数组中的重复项 II
    1365. 有多少小于当前数字的数字
  • 原文地址:https://www.cnblogs.com/randy-lo/p/12547989.html
Copyright © 2020-2023  润新知