HDU 4622 Reincarnation

枚举字符串的起点,构造后缀自动机,每次插入一个字符,就能统计得到当前不同字串的个数,预处理出所有的询问。

 1 #include<cstdio>
 2 #include<cstring>
 3 #define MAXN 2010
 4 #define MAXM 26
 5 int res[MAXN][MAXN];
 6 char str[MAXN];
 7 struct node {
 8     node *next[MAXM];
 9     node *pre;
10     int step;
11     int tot;
12 } sam[MAXN << 1];
13 node *root = &sam[0];
14 int cnt, last;
15 int ans;
16 node &newNode() {
17     sam[++cnt].tot = 0;
18     memset(sam[cnt].next, 0, sizeof(sam[cnt].next));
19     return sam[cnt];
20 }
21 void add(int idx, int step) {
22     node &p = newNode();
23     p.step = step;
24     p.pre = &p;
25     node *u = &sam[last];
26     last = cnt;
27     while (u && u->next[idx] == 0) {
28         u->next[idx] = &p;
29         p.tot += u->tot;
30         u = u->pre;
31     }
32     if (!u) {
33         p.pre = root;
34     } else {
35         node *q = u->next[idx];
36         if (q->step == u->step + 1) {
37             p.pre = q;
38         } else {
39             node &nq = newNode();
40             memcpy(nq.next, q->next, sizeof(q->next));
41             nq.step = u->step + 1;
42             nq.pre = q->pre;
43             q->pre = &nq;
44             p.pre = &nq;
45             for (; u && u->next[idx] == q; u = u->pre) {
46                 u->next[idx] = &nq;
47                 q->tot -= u->tot;
48                 nq.tot += u->tot;
49             }
50         }
51     }
52     ans += p.tot;
53 }
54 int main() {
55     int T;
56     int i, j;
57     int len;
58     int q;
59     scanf("%d", &T);
60     while (T--) {
61         scanf(" %s", str);
62         len = strlen(str);
63         for (i = 0; i < len; i++) {
64             sam[0].pre = 0;
65             sam[0].tot = 1;
66             cnt = last = 0;
67             ans = 0;
68             memset(sam[cnt].next, 0, sizeof(sam[cnt].next));
69             for (j = i; j < len; j++) {
70                 add(str[j] - 'a', j - i + 1);
71                 res[i][j] = ans;
72             }
73         }
74         scanf("%d", &q);
75         while (q--) {
76             scanf("%d%d", &i, &j);
77             printf("%d\n", res[i - 1][j - 1]);
78         }
79     }
80     return 0;
81 }
View Code

相关文章: