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