hdu 4622 Reincarnation SAM模板题
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4622
题意:给定一个长度不超过2000的字符串,之后有Q次区间查询(Q <= 10000),问区间中不同的子串数为多少?
学习资料: 知乎
SAM解析:
看了clj的PPT,对于最后为什么这样子插入节点还是有些不懂... 下面先讲讲一些理解
1.找出母串A中的所有子串可以看做是先找出A串的所有后缀,再在后缀中找出前缀(后缀中找前缀);其中的init(初始状态)是指可以匹配所有后缀的原始状态,即可以对每个后缀进行trans(init,suf)到end状态,不要想着从A串开头进行匹配;
2.一个状态s由所有Right集合是Right(s)的字符串组成
Right集合相同只能说明串之间构成包含关系,如a,b子串的Right集合相同,并且max(a) < min(b)只能说明a是b串的后缀。
注:其中的max、min表示的是在母串中出现的结束位置所构成的集合为Right时的字符串(不止一个)的长度的最大/小值;
3.在构造后缀自动机时,step表示该字符所在的后缀的下标,即每次在前一个字符的基础之上+1.并且由于前一字符的Right集合中包含L+1,但是要使得状态能够通过字符为ch的边转移还需要g[][v]不等于0,这时就需要回溯到某一个g[][v] != 0的祖先节点。
注:祖先节点的Right包含后代节点,因为祖先节点表示的路径是后代节点路径的后缀,出现的位置更多;
4.step表示的含义?以及为何插入查找的原理?
令当前还未插入的状态为trans(init,T),其中T表示A[1...L-1],当前待插入的字符x为A[L],其中step[x] = L+1,(step表示字符x是当前要建的后缀自动机字符串的第几个)之后在Right集合含有L的状态中查找第一个可通过边x转移的状态p,
如果不考虑子串是否相同,则Tx的后缀数量为step[x],由于是按照pre向上查找的,所以当找到p时,我们需要知道以p为后缀的子串有多少也是以x为后缀的?
这时候就用到了“压缩”,因为p的父节点们都符合条件(父节点的Right[L] = x,都是Tx的后缀),只需要压缩q和q的父节点p的空隙(step之间的差值为1),即可知道在状态为Tx时,有多少Tx的后缀已经存在~~,这时相减即可知道新添加的子串数量;
代码参考:JeraKrs
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std; #define maxn 2007
#define SIGMA_SIZE 26 struct SAM{
int sz,tot,last;
int g[maxn<<][SIGMA_SIZE],pre[maxn<<],step[maxn<<]; void newNode(int s){
step[++sz] = s;
pre[sz] = ;
memset(g[sz],,sizeof(g[sz]));
} void init(){
tot = ;
sz = ; last = ;
newNode();
} int idx(char ch){return ch - 'a';} int Insert(char ch){
newNode(step[last]+);
int v = idx(ch), p = last, np = sz; while(p && !g[p][v])
g[p][v] = np,p = pre[p]; //知道找到Right集合中包含x的边的祖宗节点 if(p){
int q = g[p][v];
if(step[q] == step[p] + )
pre[np] = q;
else{
newNode(step[p]+);
int nq = sz; //nq替换掉q节点
for(int i = ;i < SIGMA_SIZE;i++)
g[nq][i] = g[q][i]; 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] = ; tot += step[np] - step[pre[np]];
last = np;
return tot;
}
}SA;
char str[maxn];
int ans[maxn][maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--){
scanf("%s",str);
int len = strlen(str);
for(int i = ;i < len;i++){
SA.init();
for(int j = i;j < len;j++){
ans[i][j] = SA.Insert(str[j]);
}
}
int Q, l, r;
scanf("%d",&Q);
while(Q--){
scanf("%d%d",&l,&r);
printf("%d\n",ans[--l][--r]);
}
}
}
hdu 4622 Reincarnation SAM模板题的更多相关文章
- HDU 4622 Reincarnation Hash解法详解
今天想学字符串hash是怎么弄的.就看到了这题模板题 http://acm.hdu.edu.cn/showproblem.php?pid=4622 刚开始当然不懂啦,然后就上网搜解法.很多都是什么后缀 ...
- hdu 4622 Reincarnation(后缀数组)
hdu 4622 Reincarnation 题意:还是比较容易理解,给出一个字符串,最长2000,q个询问,每次询问[l,r]区间内有多少个不同的字串. (为了与论文解释统一,这里解题思路里sa数组 ...
- HDU 2222 AC自动机模板题
题目: http://acm.hdu.edu.cn/showproblem.php?pid=2222 AC自动机模板题 我现在对AC自动机的理解还一般,就贴一下我参考学习的两篇博客的链接: http: ...
- HDU 1251 Trie树模板题
1.HDU 1251 统计难题 Trie树模板题,或者map 2.总结:用C++过了,G++就爆内存.. 题意:查找给定前缀的单词数量. #include<iostream> #incl ...
- HDU 3065 (AC自动机模板题)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3065 题目大意:多个模式串,范围是大写字母.匹配串的字符范围是(0~127).问匹配串中含有哪几种模 ...
- HDU 2896 (AC自动机模板题)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2896 题目大意:多个模式串.多个匹配串.其中串的字符范围是(0~127).问匹配串中含有哪几个模式串 ...
- HDU 4622 Reincarnation 后缀自动机
模板来源:http://blog.csdn.net/zkfzkfzkfzkfzkfzkfzk/article/details/9669747 解法参考:http://blog.csdn.net/dyx ...
- hdu 1711 KMP算法模板题
题意:给你两个串,问你第二个串是从第一个串的什么位置開始全然匹配的? kmp裸题,复杂度O(n+m). 当一个字符串以0为起始下标时.next[i]能够描写叙述为"不为自身的最大首尾反复子串 ...
- HDU 2544 最短路(模板题)
求1到N的最短路径,模板题,以1为源点,用dijkstra算法(可以用优先级队列优化) #include <iostream> #include <algorithm> #in ...
随机推荐
- Java(Android)编程思想笔记02:组合与继承、final、策略设计模式与适配器模式、内部类、序列化控制(注意事项)
1.组合和继承之间的选择 组合和继承都允许在新的类中放置子对象,组合是显式的这样做,而继承则是隐式的做. 组合技术通常用于想在新类中使用现有类的功能而非它的接口这种情形.即在新类中嵌入某个对象,让其实 ...
- uva10004 Bicoloring 黑白染色问题,DFS
又是水题,最近切题目只能切出水题...orz 给出一个联通图,要求在个点上染上两种颜色,相邻的点颜色不能相同,看能不能染色成功. 用dfs搜索一个点的每条边,着色递归,如果已经染过色的且颜色出现矛盾就 ...
- centos安装ftp
yum install -y vsftpd安装vsftpd service vsftpd start 启动vsftpd vim /etc/vsftpd/vsftpd.conf 将anonymous_e ...
- CF Tanya and Postcard
Tanya and Postcard time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- [未完成]关于Oracle知识总结
关于Oracle知识总结关于Oracle知识总结关于Oracle知识总结关于Oracle知识总结
- JAVA基础之理解JNI原理
JNI是JAVA标准平台中的一个重要功能,它弥补了JAVA的与平台无关这一重大优点的不足,在JAVA实现跨平台的同时,也能与其它语言(如C.C++)的动态库进行交互,给其它语言发挥优势的机会. 有了J ...
- 查锁表及kill
当一个表一直被锁住而无法进行操作的时候,可以用如下方法 select l.session_id sid, s.serial#, l.locked_mode 锁模式, l.oracle_username ...
- 基于ArcEngine与C#的鹰眼地图实现
鹰眼图是对全局地图的一种概略表达,具有与全局地图的空间参考和空间范围.为了更好起到空间提示和导航作用,有些还具备全局地图中重要地理要素,如主要河流.道路等的概略表达.通过两个axMapControl控 ...
- 核心概念 —— 门面(Facades)
1.简介 门面为应用的服务容器中的绑定类提供了一个"静态"接口.Laravel 内置了很多门面,你可能在不知道的情况下正在使用它们.Laravel 的门面作为服务容器中的底层类的& ...
- base.AutoScaleMode = AutoScaleMode.Font; 方法“InitializeComponent”内的代码由设计器生成,不应手动修改。请移除任何更改,然后尝试重新打开设计器”。
http://www.taohuiduo.com 反编译后的工程文件用VS2010打开后,在打开窗体时会出现一系列错误提示: 第一种情况: “设计器无法处理第 152 行的代码: base.AutoS ...