zoukankan      html  css  js  c++  java
  • hdu4622(后缀自动机模板)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4622

    题意: 先输入一个长度为 n 的字符串, 然后有 q 个形如 l, r 的询问, 对于每个询问输出区间 [l, r] 中有多少不同的子串

    思路: 后缀自动机模板

    代码:

      1 // 后缀自动机要理解其含义,从起点到每个点的不同路径,就是不同的子串。
      2 // 到每一个点,不同路径,其实就是以这个点为最后一个字符的后缀,长度是介于(p->fa->len,p->len]之间的,个数也就清楚了。
      3 // 而且这个其实是动态变化的,每加入一个字符,就可以知道新加了几个不同子串。
      4 // 加个pos,记录位置,这样就很容易预处理了。
      5 
      6 #include <iostream>
      7 #include <stdio.h>
      8 #include <string.h>
      9 using namespace std;
     10 
     11 const int CHAR = 26;
     12 const int MAXN = 2e3 + 10;
     13 
     14 struct SAM_Node{
     15     SAM_Node *fa, *next[CHAR];
     16     int len, id, pos;
     17     SAM_Node(){};
     18     SAM_Node(int _len){
     19         fa = 0;
     20         len = _len;
     21         memset(next, 0, sizeof(next));
     22     }
     23 };
     24 
     25 SAM_Node SAM_node[MAXN << 1], *SAM_root, *SAM_last;
     26 int SAM_size;
     27 
     28 SAM_Node *newSAM_Node(int len){
     29     SAM_node[SAM_size] = SAM_Node(len);
     30     SAM_node[SAM_size].id = SAM_size;
     31     return &SAM_node[SAM_size++];
     32 }
     33 
     34 SAM_Node *newSAM_Node(SAM_Node *p){
     35     SAM_node[SAM_size] = *p;
     36     SAM_node[SAM_size].id = SAM_size;
     37     return &SAM_node[SAM_size++];
     38 }
     39 
     40 void SAM_init(void){
     41     SAM_size = 0;
     42     SAM_root = SAM_last = newSAM_Node(0);
     43     SAM_node[0].pos = 0;
     44 }
     45 
     46 void SAM_add(int x, int len){
     47     SAM_Node *p = SAM_last, *np = newSAM_Node(p->len + 1);
     48     np->pos = len;
     49     SAM_last = np;
     50     for(; p && !p->next[x]; p = p->fa) p->next[x] = np;
     51     if(!p){
     52         np->fa = SAM_root;
     53         return;
     54     }
     55     SAM_Node *q = p->next[x];
     56     if(q->len == p->len + 1){
     57         np->fa = q;
     58         return;
     59     }
     60     SAM_Node *nq = newSAM_Node(q);
     61     nq->len = p->len + 1;
     62     q->fa = nq;
     63     np->fa = nq;
     64     for(; p && p->next[x] == q; p = p->fa) p->next[x] = nq;
     65 }
     66 
     67 void SAM_build(char *s){
     68     SAM_init();
     69     int len = strlen(s);
     70     for(int i = 0; i < len; i++){
     71         SAM_add(s[i] - 'a', i + 1);
     72     }
     73 }
     74 
     75 int Q[MAXN][MAXN];
     76 char str[MAXN];
     77 
     78 int main(void){
     79     int t;
     80     scanf("%d", &t);
     81     while(t--){
     82         scanf("%s", str);
     83         memset(Q, 0, sizeof(Q));
     84         int n = strlen(str);
     85         for(int i = 0; i < n; i++){
     86             SAM_init();
     87             for(int j = i; j < n; j++){
     88                 SAM_add(str[j] - 'a', j - i + 1);
     89             }
     90             for(int j = 1; j < SAM_size; j++){
     91                 Q[i][SAM_node[j].pos + i - 1] += SAM_node[j].len - SAM_node[j].fa->len;
     92             }
     93             for(int j = i + 1; j < n; j++){
     94                 Q[i][j] += Q[i][j - 1];
     95             }
     96         }
     97         int q, l, r;
     98         scanf("%d", &q);
     99         while(q--){
    100             scanf("%d%d", &l, &r);
    101             printf("%d
    ", Q[l - 1][r - 1]);
    102         }
    103     }
    104     return 0;
    105 }
    View Code
  • 相关阅读:
    HDU 3081 Marriage Match II
    HDU 4292 Food
    HDU 4322 Candy
    HDU 4183 Pahom on Water
    POJ 1966 Cable TV Network
    HDU 3605 Escape
    HDU 3338 Kakuro Extension
    HDU 3572 Task Schedule
    HDU 3998 Sequence
    Burning Midnight Oil
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/7474267.html
Copyright © 2011-2022 走看看