hdu4622(后缀自动机模板)

Posted ygeloutingyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n", Q[l - 1][r - 1]);
102         }
103     }
104     return 0;
105 }
View Code

 

以上是关于hdu4622(后缀自动机模板)的主要内容,如果未能解决你的问题,请参考以下文章

HDU4622Reincarnation(后缀自动机)

hdu4622-Reincarnation(后缀自动机)

HDU4622 Reincarnation 后缀自动机

HDU 4622 Reincarnation 后缀自动机

HDU 4622 Reincarnation (区间不相同子串个数:字符串哈希 | 后缀数组 | 后缀自动机)

HDU4622 (查询一段字符串的不同子串个数,后缀自动机)