HDU 4622 Reincarnation (查询一段字符串的不同子串个数,后缀自动机)
Reincarnation
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 843 Accepted Submission(s): 283
Given you a string s consist of lower-case English letters only,denote f(s) as the number of distinct sub-string of s.
And you have some query,each time you should calculate f(s[l...r]), s[l...r] means the sub-string of s start from l end at r.
For each test cases,the first line contains a string s(1 <= length of s <= 2000).
Denote the length of s by n.
The second line contains an integer Q(1 <= Q <= 10000),denote the number of queries.
Then Q lines follows,each lines contains two integer l, r(1 <= l <= r <= n), denote a query.
bbaba
5
3 4
2 2
2 5
2 4
1 4
baaba
5
3 3
3 4
1 4
3 5
5 5
1
7
5
8
1
3
8
5
1
I won't do anything against hash because I am nice.Of course this problem has a solution that don't rely on hash.
刚刚学了下后缀自动机,然后把这题先A掉。
这题就是查询一个区间内的不同子串的个数。
如果单单是求一个字符串的不同子串个数,无论是后缀数组还是后缀自动机都非常容易实现。
N<=2000.
我是用后缀自动机预处理出所有区间的不同子串个数。
建立n次后缀自动机。
后缀自动机要理解其含义,从起点到每个点的不同路径,就是不同的子串。
到每一个点,不同路径,其实就是以这个点为最后一个字符的后缀,长度是介于(p->fa->len,p->len]之间的,个数也就清楚了。
而且这个其实是动态变化的,每加入一个字符,就可以知道新加了几个不同子串。
加个pos,记录位置,这样就很容易预处理了。
学了一天的后缀自动,在世界冠军cxlove的博客中一直看SAM,终于有点理解了,Orz,太神奇了。
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std; const int CHAR = ;
const int MAXN = ;
struct SAM_Node
{
SAM_Node *fa,*next[CHAR];
int len;
int id,pos;
SAM_Node(){}
SAM_Node(int _len)
{
fa = ;
len = _len;
memset(next,,sizeof(next));
}
};
SAM_Node SAM_node[MAXN*], *SAM_root, *SAM_last;
int SAM_size;
SAM_Node *newSAM_Node(int len)
{
SAM_node[SAM_size] = SAM_Node(len);
SAM_node[SAM_size].id = SAM_size;
return &SAM_node[SAM_size++];
}
SAM_Node *newSAM_Node(SAM_Node *p)
{
SAM_node[SAM_size] = *p;
SAM_node[SAM_size].id = SAM_size;
return &SAM_node[SAM_size++];
}
void SAM_init()
{
SAM_size = ;
SAM_root = SAM_last = newSAM_Node();
SAM_node[].pos = ;
}
void SAM_add(int x,int len)
{
SAM_Node *p = SAM_last, *np = newSAM_Node(p->len+);
np->pos = len;
SAM_last = np;
for(;p && !p->next[x];p = p->fa)
p->next[x] = np;
if(!p)
{
np->fa = SAM_root;
return;
}
SAM_Node *q = p->next[x];
if(q->len == p->len + )
{
np->fa = q;
return;
}
SAM_Node *nq = newSAM_Node(q);
nq->len = p->len + ;
q->fa = nq;
np->fa = nq;
for(;p && p->next[x] == q;p = p->fa)
p->next[x] = nq;
}
void SAM_build(char *s)
{
SAM_init();
int len = strlen(s);
for(int i = ;i < len;i++)
SAM_add(s[i] - 'a',i+);
} int Q[MAXN][MAXN];
char str[MAXN];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",str);
int n = strlen(str);
memset(Q,,sizeof(Q));
for(int i = ;i < n;i++)
{
SAM_init();
for(int j = i;j < n;j++)
{
SAM_add(str[j]-'a',j-i+);
}
for(int j = ;j < SAM_size;j++)
{
Q[i][SAM_node[j].pos-+i]+=SAM_node[j].len - SAM_node[j].fa->len;
}
for(int j = i+;j < n;j++)
Q[i][j] += Q[i][j-];
}
int M;
int u,v;
scanf("%d",&M);
while(M--)
{
scanf("%d%d",&u,&v);
u--;v--;
printf("%d\n",Q[u][v]);
}
}
return ;
}
HDU 4622 Reincarnation (查询一段字符串的不同子串个数,后缀自动机)的更多相关文章
- HDU4622 (查询一段字符串的不同子串个数,后缀自动机)
http://acm.hdu.edu.cn/showproblem.php?pid=4622 题意:给出一个字符串和q次询问,每次询问[l,r]区间内不同子串的个数 分析: N<=2000. 我 ...
- hdu 4622 Reincarnation(后缀数组)
hdu 4622 Reincarnation 题意:还是比较容易理解,给出一个字符串,最长2000,q个询问,每次询问[l,r]区间内有多少个不同的字串. (为了与论文解释统一,这里解题思路里sa数组 ...
- HDU 4622 Reincarnation Hash解法详解
今天想学字符串hash是怎么弄的.就看到了这题模板题 http://acm.hdu.edu.cn/showproblem.php?pid=4622 刚开始当然不懂啦,然后就上网搜解法.很多都是什么后缀 ...
- hdu 4622 Reincarnation 字符串hash 模板题
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4622 题意:给定一个长度不超过2000的字符串,之后有不超过1e5次的区间查询,输出每次查询区间中不同 ...
- 字符串(后缀自动机):HDU 4622 Reincarnation
Reincarnation Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)To ...
- hdu 4622 Reincarnation SAM模板题
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4622 题意:给定一个长度不超过2000的字符串,之后有Q次区间查询(Q <= 10000),问区 ...
- HDU 4622 Reincarnation(后缀自动机)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=4622 [题目大意] 给出一个长度不超过2000的字符串,有不超过10000个询问,问[L,R]子串 ...
- HDU 4622 Reincarnation 后缀自动机 // BKDRHash(最优hash)
Reincarnation Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) P ...
- hdu多校第一场 1006 (hdu6583)Typewriter dp/后缀自动机
题意: 有个打字机,在当前字符串后新加一个字花费p,把当前字符串的一个连续子串拷贝到当前字符串的末尾花费q,给定一个字符串,求用打字机打出这个字符串的最小花费. 题解: 容易想到用dp 记dp[i]为 ...
随机推荐
- The SQL Server Service Broker for the current database is not enabled
把一个数据恢复至另一个服务器上,出现了一个异常: The SQL Server Service Broker for the current database is not enabled, and ...
- C#基础-关于用json给控制台程序传值的坑
上周遇到了一个非常诡异的坑,首先写了两个程序,第一个程序输出成dll,第二个程序是控制台程序. 在第一个程序里,我使用了process去启动第二个程序,同时传入了一个Json作为参数,即: Proce ...
- c# 连接Mysql数据库
mysql.data.dll下载_c#连接mysql必要插件 全部版本下载:http://hovertree.com/h/bjaf/0sft36s9.htm mysql.data.dll是C#操作MY ...
- 把cookie以json形式返回,用js来set cookie.(解决手机浏览器未知情况下获取不到cookie)
.继上一篇随笔,链接点我,解决手机端cookie的问题. .上次用cookie+redis实现了session,并且手机浏览器可能回传cookies有问题,所以最后用js取出cookie跟在请求的ur ...
- 关于项目中值对象Identifier的设计-领域驱动
到现在为止做了不项目,发现每个实体都会有个相应的值对象. 先简单说一下值对象和实体之间的区别: (以下内容来着<领域驱动设计>一书) 当一个小孩画画的时候,他注意的是画笔的颜色和笔尖的粗细 ...
- 简单介绍JSON
如下图:
- position: fixed用在iframe里面失效了
iframe真是各种坑啊,,,可是找不到别的代替 $(parent.window).scroll(function(){ $('固定元素').css({ top : $(parent.window). ...
- 2-1 git合并 打tag
tag常用命令(仅供参考): git tag -a V1.4 -m "1.4" 创建一个tag git tag 查看本地tag git tag -d V1.1 删除本地tag g ...
- iOS 二维码扫描
// 导入 AVFoundation.framwork 框架#import "HDCodeViewController.h" #import "HDNormalViewC ...
- va_start和va_end使用详解
本文主要介绍va_start和va_end的使用及原理. 介绍这两个宏之前先看一下C中传递函数的参数时的用法和原理: 1.在C中,当我们无法列出传递函数的所有实参的类型和数目时,可以用省略号指定参数表 ...