Reincarnation

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 843    Accepted Submission(s): 283

Problem Description
Now you are back,and have a task to do:
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.
 
Input
The first line contains integer T(1<=T<=5), denote the number of the test cases.
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.
 
Output
For each test cases,for each query,print the answer in one line.
 
Sample Input
2
bbaba
5
3 4
2 2
2 5
2 4
1 4
baaba
5
3 3
3 4
1 4
3 5
5 5
 
Sample Output
3
1
7
5
8
1
3
8
5
1

Hint

I won't do anything against hash because I am nice.Of course this problem has a solution that don't rely on hash.

 
Source
 
Recommend
zhuyuanchen520
 

刚刚学了下后缀自动机,然后把这题先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 (查询一段字符串的不同子串个数,后缀自动机)的更多相关文章

  1. HDU4622 (查询一段字符串的不同子串个数,后缀自动机)

    http://acm.hdu.edu.cn/showproblem.php?pid=4622 题意:给出一个字符串和q次询问,每次询问[l,r]区间内不同子串的个数 分析: N<=2000. 我 ...

  2. hdu 4622 Reincarnation(后缀数组)

    hdu 4622 Reincarnation 题意:还是比较容易理解,给出一个字符串,最长2000,q个询问,每次询问[l,r]区间内有多少个不同的字串. (为了与论文解释统一,这里解题思路里sa数组 ...

  3. HDU 4622 Reincarnation Hash解法详解

    今天想学字符串hash是怎么弄的.就看到了这题模板题 http://acm.hdu.edu.cn/showproblem.php?pid=4622 刚开始当然不懂啦,然后就上网搜解法.很多都是什么后缀 ...

  4. hdu 4622 Reincarnation 字符串hash 模板题

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4622 题意:给定一个长度不超过2000的字符串,之后有不超过1e5次的区间查询,输出每次查询区间中不同 ...

  5. 字符串(后缀自动机):HDU 4622 Reincarnation

    Reincarnation Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)To ...

  6. hdu 4622 Reincarnation SAM模板题

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4622 题意:给定一个长度不超过2000的字符串,之后有Q次区间查询(Q <= 10000),问区 ...

  7. HDU 4622 Reincarnation(后缀自动机)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=4622 [题目大意] 给出一个长度不超过2000的字符串,有不超过10000个询问,问[L,R]子串 ...

  8. HDU 4622 Reincarnation 后缀自动机 // BKDRHash(最优hash)

    Reincarnation Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) P ...

  9. hdu多校第一场 1006 (hdu6583)Typewriter dp/后缀自动机

    题意: 有个打字机,在当前字符串后新加一个字花费p,把当前字符串的一个连续子串拷贝到当前字符串的末尾花费q,给定一个字符串,求用打字机打出这个字符串的最小花费. 题解: 容易想到用dp 记dp[i]为 ...

随机推荐

  1. MS SQL验证字符串是否包含有大小写字母

    昨晚有实现一个小功能,就是在MS SQL Server中,检查字符串是否包含有大小写字母.通常应用在字符串的复杂度. ) = N'SDFfgGRYJhhTYUJ' IF LOWER(@s) COLLA ...

  2. Solr3.6.1 在Tomcat6下的环境搭建

    Solr3.6.1 在Tomcat6下的环境搭建 Tomcat路径:D:\prg\apache-tomcat-6-solr 简写为tomcat_home Solr文件下载保存路径为:F:\softwa ...

  3. WPF资源使用

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x ...

  4. wampsever在线模式和离线模式有什么区别

    我们在开发网站的时候经常会使用到wampsever服务器,在测试项目的时候我们会经常发现,wampsever服务器在线模式和离线模式都可以使用并且测试,还有一个现象就是我们在测试无线网络,用手机访问的 ...

  5. Java中随机数的产生方式与原理

    查阅随机数相关资料,特做整理 首先说一下java中产生随机数的几种方式 在j2se中我们可以使用Math.random()方法来产生一个随机数,这个产生的随机数是0-1之间的一个double,我们可以 ...

  6. mybatis报错invalid types () or values ()解决方法

      原因: Pojo类User没提供无参数构造方法, 加上该构造方法后,问题解决 ### Cause: org.apache.ibatis.reflection.ReflectionException ...

  7. python基础之面向对象高级编程

    面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个"函数"供使用(可以讲多函数中公用的变量封装到对象中) ...

  8. 【夯实PHP基础系列】JQuery easyUI的使用

    最近在做一个公司的后台项目中,接触到 JQuery easyUI前端框架,被她简洁的代码和简单有效的ajax交互所深深吸引. 体会有以下3个方面: 1)快速创建表格的能力: 后端程序,比如PHP只需要 ...

  9. WebAPI生成可导入到PostMan的数据

    一.前言 现在使用WebAPI来作为实现企业服务化的需求非常常见,不可否认它也是很便于使用的,基于注释可以生成对应的帮助文档(Microsoft.AspNet.WebApi.HelpPage),但是比 ...

  10. Linux(Centos)之安装Java JDK及注意事项

    1.准备工作 a.因为Java JDK区分32位和64位系统,所以在安装之前必须先要判断以下我们的Centos系统为多少位系统,命令如下: uname -a 解释:如果有x86_64就是64位的,没有 ...