zoukankan      html  css  js  c++  java
  • HDU-2222-Keywords Search(AC自动机)

    这题是AC自动机的模板题,AC自动机是结合了字典树,和KMP两种算法产生的,去年为了学习AC自动机去看了前面说的两种算法,但是可能因为KMP当时理解的不够透彻所以这题当时也只是半背代码的做出来了,没多久就忘了。经过那么久的学习感觉KMP掌握的差不多了,今天回顾了一下AC自动机,并记录一下模板

    • AC自动机
      Accepted 2222 327MS 56848K 1991 B G++
      #include "cstdio"
      #include "cstring"
      #include "cstdlib"
      #include "queue"
      using namespace std;
      const int MAXS = 1000005;
      const int MAXP = 55;
      const int SIZE = 26;
      struct Tree {
          int tail;
          Tree* next[SIZE];
          Tree* fail;
      }* root;
      char p[MAXP], s[MAXS];
      Tree* init() {
          Tree* point = (Tree*)malloc(sizeof(Tree));
          point->tail = 0;
          memset(point->next, NULL, sizeof(point->next));
          point->fail = NULL;
          return point;
      }
      void insert(char* p) {
          Tree* point = root;
          for (int i = 0; p[i]; i++) {
              int index = p[i] - 'a';
              if (point->next[index] == NULL) {
                  point->next[index] = init();
              }
              point = point->next[index];
          }
          point->tail++;
      }
      void build() {
          queue<Tree*> q;
          Tree* point;
          Tree* p1;
          Tree* p2;
          q.push(root);
          while (!q.empty()) {
              point = q.front();
              q.pop();
              for (int i = 0; i < SIZE; i++) {
                  if (point->next[i] != NULL) {
                      p1 = point->fail;
                      p2 = point->next[i];
                      while (p1 != NULL) {
                          if (p1->next[i] != NULL) {
                              p2->fail = p1->next[i];
                              break;
                          }
                          p1 = p1->fail;
                      }
                      if (p1 == NULL) {
                          p2->fail = root;
                      }
                      q.push(p2);
                  }
              }
          }
      }
      int query(char* s) {
          int cnt = 0;
          Tree* p1;
          Tree* p2;
          p1 = root; 
          for (int i = 0; s[i]; i++) {
              int index = s[i] - 'a';
              while (p1 != root && p1->next[index] == NULL) {
                  p1 = p1->fail;
              }
              p1 = p1->next[index];
              if (p1 == NULL) {
                  p1 = root;
              }
              p2 = p1;
              while (p2 != root && p2->tail != -1) {
                  cnt += p2->tail;
                  p2->tail = -1;
                  p2 = p2->fail;
              }
          }
          return cnt;
      }
      void clear(Tree* point) {
          for (int i = 0; i < SIZE; i++) {
              if (point->next[i] != NULL) {
                  clear(point->next[i]);
              }
          }
          free(point);
      }
      int main() {
          int t, n;
          scanf("%d", &t);
          while (t--) {
              root = init();
              scanf("%d", &n);
              while (n--) {
                  scanf("%s", p);
                  insert(p);
              }
              scanf("%s", s);
              build();
              printf("%d
      ", query(s));
              clear(root);
              root = NULL;
          }
          return 0;
      } 

      build的时候网上的代码都是用自己写的队列,我一开始用自己写的队列运行时间达到了171ms,确实比库里封装的快不少,但是我还是喜欢用库里的比较保险。弄懂了KMP和字典树看一下网上的讲解就好理解了。

  • 相关阅读:
    电脑设置开机
    python 环境搭建 python-3.4.4
    遍历hashmap 的四种方法
    Java8 使用 stream().map()提取List对象的某一列值及排重
    解决 SpringMVC 非spring管理的工具类使用@Autowired注解注入DAO为null的问题
    CXF之"@XmlType.name 和 @XmlType.namespace 为类分配不同的名称"错误
    java.lang.NoSuchMethodError: javax.wsdl.xml.WSDLReader.readWSDL
    java.lang.IllegalArgumentException: URLDecoder: Illegal hex characters in escape (%) pattern
    java.lang.IllegalArgumentException: Request header is too large
    ie8 报错:意外地调用了方法或属性访问
  • 原文地址:https://www.cnblogs.com/Angel-Demon/p/10358416.html
Copyright © 2011-2022 走看看