hdu 4622 Reincarnation(SAM)
2015-11-01 23:13
441 查看
题目链接:hdu 4622 Reincarnation
解题思路
对字符串的每个后缀串构建一次后缀自动机,后缀自动机中维护一个tot记录当前串有多少个不同子串,处理出二维ans数组。代码
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 4005; const int SIGMA_SIZE = 26; struct SAM { int sz, last; int g[maxn<<1][SIGMA_SIZE], pre[maxn<<1], step[maxn<<1]; int tot; void newNode(int s) { step[++sz] = s; pre[sz] = 0; memset(g[sz], 0, sizeof(g[sz])); } int idx(char ch) { return ch -'a'; } void init() { tot = 0; sz = 0, last = 1; newNode(0); } int insert(char ch) { newNode(step[last] + 1); int v = idx(ch), p = last, np = sz; while (p && !g[p][v]) { g[p][v] = np; p = pre[p]; } if (p) { int q = g[p][v]; if (step[q] == step[p] + 1) pre[np] = q; else { newNode(step[p] + 1); int nq = sz; for (int j = 0; j < SIGMA_SIZE; j++) g[nq][j] = g[q][j]; pre[nq] = pre[q]; pre[np] = pre[q] = nq; while (p && g[p][v] == q) { g[p][v] = nq; p = pre[p]; } } } else pre[np] = 1; tot += step[np] - step[pre[np]]; last = np; return tot; } }SA; char str[maxn]; int ans[maxn][maxn]; int main () { int cas; scanf("%d", &cas); while (cas--) { scanf("%s", str); int n = strlen(str), u, v; for (int i = 0; i < n; i++) { SA.init(); for (int j = i; j < n; j++) ans[i+1][j+1] = SA.insert(str[j]); } scanf("%d", &n); while (n--) { scanf("%d%d", &u, &v); printf("%d\n", ans[u][v]); } } return 0; }
相关文章推荐
- android的TextView的TextWatcher使用
- 内存管理笔记(分页,分段,逻辑地址,物理地址与地址转换方式)
- 《探索需求》读书笔记三
- 配置spring的事务管理
- 冲刺汇总贴
- Java的学习笔记
- Java enum的用法详解
- 十一月初始。
- sed命令详解
- 自定义UISlider的样式和滑块
- 浅识排序----冒泡排序
- apache httpd学习笔记二 - 命令
- 编译原理学习笔记二
- 二叉树精选
- log4j:ERROR Failed to load driver问题
- 20151024_004_C#基础知识(C#中的访问修饰符,继承,new关键字,里氏转换,is 和 as,多态,序列化与反序列化)
- Android中对加载大图的处理
- HDU 5531 Rebuild ——— 2015ACM-ICPC亚洲区长春站
- tail 命令
- d-link DI-7300 DI-7200 开启路由模式