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 }