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
 
 

题意: 给一个字符串长度最大2000,给出Q个查询[l,r]包含多少种连续的子串。
解析: 后缀自动机轻松过,先对查询离线排序,对于左端点相同的建立一个后缀自动
机,字符串长度最大只有2000,所以最后只用建2000个,每个sam插入的字符最多也就
2000,时间肯定是够的。

代码

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=;
struct SAM
{
int ch[maxn][];
int pre[maxn],step[maxn];
int last,id;
void init()
{
last=id=;
memset(ch[],-,sizeof(ch[]));
pre[]=-; step[]=;
}
void Insert(int c) //字符转化为数
{
int p=last,np=++id;
step[np]=step[p]+;
memset(ch[np],-,sizeof(ch[np]));
while(p!=-&&ch[p][c]==-) ch[p][c]=np,p=pre[p];
if(p==-) pre[np]=;
else
{
int q=ch[p][c];
if(step[q]!=step[p]+)
{
int nq=++id;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
step[nq]=step[p]+;
pre[nq]=pre[q];
pre[np]=pre[q]=nq;
while(p!=-&&ch[p][c]==q) ch[p][c]=nq,p=pre[p];
}
else pre[np]=q;
}
last=np;
}
int GetCnt()
{
int ret=;
for(int i=id;i>=;i--) ret+=step[i]-step[pre[i]];
return ret;
}
}sam;
char S[maxn/];
struct Ques
{
int l,r,id;
Ques(int l=,int r=,int id=):l(l),r(r),id(id){}
bool operator < (const Ques& t) const
{
if(l!=t.l) return l<t.l;
return r<t.r;
}
}q[];
int Q,ans[];
void solve()
{
sort(q,q+Q);
int last;
for(int i=;i<Q;i++)
{
if(i==||q[i].l!=q[i-].l)
{
sam.init();
last=q[i].l;
}
for(;last<=q[i].r;last++) sam.Insert(S[last]-'a');
ans[q[i].id]=sam.GetCnt();
}
for(int i=;i<Q;i++) printf("%d\n",ans[i]);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",S+);
int len=strlen(S);
scanf("%d",&Q);
int l,r,id;
for(int i=;i<Q;i++)
{
scanf("%d%d",&l,&r);
q[i]=Ques(l,r,i);
}
solve();
}
return ;
}

hdu4622-Reincarnation(后缀自动机)的更多相关文章

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

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

  2. HDU 4622 Reincarnation 后缀自动机

    模板来源:http://blog.csdn.net/zkfzkfzkfzkfzkfzkfzk/article/details/9669747 解法参考:http://blog.csdn.net/dyx ...

  3. HDU-4622 Reincarnation 后缀数组 | Hash,维护和,扫描

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4622 题意:给一个字符串,询问某字串的不同字串的个数. 可以用后缀数组来解决,复杂度O(n).先求出倍 ...

  4. HDU4622:Reincarnation(后缀数组,求区间内不同子串的个数)

    Problem Description Now you are back,and have a task to do: Given you a string s consist of lower-ca ...

  5. [hdu4622 Reincarnation]后缀数组

    题意:给一个长度为2000的字符串,10000次询问区间[L,R]内的不同子串的个数 思路:对原串的每个前缀求一边后缀数组,询问[L,R]就变成了询问[L,n]了,即求一个后缀里面出现了多少个不同子串 ...

  6. Hdu 4622 Reincarnation(后缀自动机)

    /* 字符串长度较小, 可以离线或者直接与处理所有区间的答案 动态加入点的时候, 因为对于其他点的parent构造要么没有影响, 要么就是在两个节点之间塞入一个点, 对于minmax的贡献没有改变 所 ...

  7. 【HDU4622】Reincarnation(后缀自动机)

    [HDU4622]Reincarnation(后缀自动机) 题面 Vjudge 题意:给定一个串,每次询问l~r组成的子串的不同子串个数 题解 看到字符串的大小很小 而询问数太多 所以我们预处理任意的 ...

  8. HDU 4622 Reincarnation (查询一段字符串的不同子串个数,后缀自动机)

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

  9. Reincarnation HDU - 4622 (后缀自动机)

    Reincarnation \[ Time Limit: 3000 ms\quad Memory Limit: 65536 kB \] 题意 给出一个字符串 \(S\),然后给出 \(m\) 次查询, ...

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

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

随机推荐

  1. 对Ul下的li标签执行点击事件——如何获取你所点击的标签

    问题所来:做项目时,一般的数据都是用循环动态加载出来的,结构都是一样的,只是绑定的值不同,如何对相同的标签做处理的问题就来了. 例如:点谁就显示谁的数值 <ul > <li id=& ...

  2. java-下载excel

    在java程序里面处理excel,我觉得比较方便的方式是先做出一个excel的模板(比如定义表头信息.表格名称等),然后根据这个模板往里面填充数据 我这里演示的是使用poi处理2007以上版本的exc ...

  3. 关于ionic的一些坑(1)

    既然来了,总要留下点什么证明自己来过不是,今天就扒一扒自己在ionic上面遇到的坑,因为在项目中2还没出来,所以现在所遇到的都是1中的,关于2的,待老夫以后详细摸索之后在与君细细道来. 1.ionic ...

  4. 限定checkbox最多选中数量

    一.概述: checkbox是我们在编写网页的时候经常使用的多选框,但是有些时候我们会限定最多选中的数量,如何限定呢? 下面这例子限定了最多选中两个元素,并且将这两个选中的源依次显示在一个文本框里: ...

  5. js解析json,js转换json成map,获取map的key,value

    json串格式 { "10.10.11.1": { "target_1": "34.2", "target_3": &q ...

  6. 常用语言api语法Cheat Sheet

    http://overapi.com/jquery/ OverAPI.com Python jQuery NodeJS PHP Java Ruby Javascript ActionScript CS ...

  7. 【Android】Activity的菜单机制和方法解析

    Activity有一套机制来实现对菜单的管理,方法如下: 1. 初始化菜单 public boolean onCreateOptionsMenu(Menu menu) 此方法用于初始化菜单,其中men ...

  8. [Redux] Implementing combineReducers() from Scratch

    The combineReducers function we used in previous post: const todoApp = combineReducers({ todos, visi ...

  9. Java基础知识强化56:经典排序之快速排序(QuickSort)

    1. 快速排序的原理: 快速排序(Quicksort)是对冒泡排序的一种改进. 快速排序由C. A. R. Hoare在1962年提出.它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其 ...

  10. zip命令的使用

    zip命令可以用来将文件压缩成为常用的zip格式.unzip命令则用来解压缩zip文件. 1. 我想把一个文件abc.txt和一个目录dir1压缩成为yasuo.zip: # zip -r yasuo ...