题意:给一个长度为2000的字符串,10000次询问区间[L,R]内的不同子串的个数

思路:对原串的每个前缀求一边后缀数组,询问[L,R]就变成了询问[L,n]了,即求一个后缀里面出现了多少个不同子串。于是对所有大于等于L的后缀统计一遍即可。

  1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; #define X first
#define Y second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a))
#define copy(a, b) memcpy(a, b, sizeof(a)) typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull; #ifndef ONLINE_JUDGE
void RI(vector<int>&a,int n){a.resize(n);for(int i=;i<n;i++)scanf("%d",&a[i]);}
void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?:-;
while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
void print(T*p, T*q){int d=p<q?:-;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
#endif
template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}
template<typename T>
void V2A(T a[],const vector<T>&b){for(int i=;i<b.size();i++)a[i]=b[i];}
template<typename T>
void A2V(vector<T>&a,const T b[]){for(int i=;i<a.size();i++)a[i]=b[i];} const double PI = acos(-1.0);
const int INF = 1e9 + ; /* -------------------------------------------------------------------------------- */ const int maxn = 2e3 + ; struct SA {
//const static int maxn = 2e3 + 7;
int sa[maxn], t[maxn], t2[maxn], c[maxn], n, m;
int Rank[maxn], Height[maxn];
int s[maxn]; void init(int n, int m, char s[]) {
for (int i = ; i < n; i ++) this->s[i] = s[i];
this->s[n] = ;
this->n = n + ;
this->m = m;
} void build() {
int i, *x = t, *y = t2;
for (i = ; i < m; i ++) c[i] = ;
for (i = ; i < n; i ++) c[x[i] = s[i]] ++;
for (i = ; i < m; i ++) c[i] += c[i - ];
for (i = n - ; i >= ; i --) sa[-- c[x[i]]] = i;
for (int k = ; k <= n; k <<= ) {
int p = ;
for (i = n - k; i < n; i ++) y[p ++] = i;
for (i = ; i < n; i ++) if (sa[i] >= k) y[p ++] = sa[i] - k;
for (i = ; i < m; i ++) c[i] = ;
for (i = ; i < n; i ++) c[x[y[i]]] ++;
for (i = ; i < m; i ++) c[i] += c[i - ];
for (i = n - ; i >= ; i --) sa[-- c[x[y[i]]]] = y[i];
swap(x, y);
p = ; x[sa[]] = ;
for (i = ; i < n; i ++) {
x[sa[i]] = y[sa[i - ]] == y[sa[i]] &&
y[sa[i - ] + k] == y[sa[i] + k]? p - : p ++;
}
if (p >= n) break;
m = p;
}
}
void getHeight() {
int i, k = ;
for (i = ; i < n; i ++) Rank[sa[i]] = i;
for (i = ; i < n; i ++) {
if (k) k --;
int j = sa[Rank[i] - ];
while (s[i + k] == s[j + k]) k ++;
Height[Rank[i]] = k;
}
}
};
SA sa;
int H[maxn][maxn], S[maxn][maxn];
char s[maxn]; int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
int T, m;
cin >> T;
while (T --) {
scanf("%s", s);
for (int i = ; s[i]; i ++) {
sa.init(i + , , s);
sa.build();
sa.getHeight();
copy(H[i], sa.Height);
copy(S[i], sa.sa);
} cin >> m;
while (m --) {
int u, v;
scanf("%d%d", &u, &v);
int *ph = H[v - ], *ps = S[v - ], common = , ans = ;
u --;
for (int i = ; i <= v; i ++) {
if (ps[i] >= u) {
ans += v - ps[i] - common;
common = INF;
}
umin(common, ph[i + ]);
}
printf("%d\n", ans);
}
}
return ;
}

[hdu4622 Reincarnation]后缀数组的更多相关文章

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

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

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

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

  3. hdu 4622 Reincarnation(后缀数组)

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

  4. 字符串数据结构模板/题单(后缀数组,后缀自动机,LCP,后缀平衡树,回文自动机)

    模板 后缀数组 #include<bits/stdc++.h> #define R register int using namespace std; const int N=1e6+9; ...

  5. HDU4622 Reincarnation【SAM】

    HDU4622 Reincarnation 给出一个串,每次询问其一个子串有多少不同的子串 按每个后缀建立\(SAM\)不断往后加字符,然后记录答案,查询的时候直接用即可 //#pragma GCC ...

  6. 后缀数组的倍增算法(Prefix Doubling)

    后缀数组的倍增算法(Prefix Doubling) 文本内容除特殊注明外,均在知识共享署名-非商业性使用-相同方式共享 3.0协议下提供,附加条款亦可能应用. 最近在自学习BWT算法(Burrows ...

  7. BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]

    4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...

  8. BZOJ 1692: [Usaco2007 Dec]队列变换 [后缀数组 贪心]

    1692: [Usaco2007 Dec]队列变换 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1383  Solved: 582[Submit][St ...

  9. POJ3693 Maximum repetition substring [后缀数组 ST表]

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9458   Acc ...

随机推荐

  1. BJDCTF 2nd web

    先贴一下Y1ng大佬的WP elementmaster 脑洞确实大,源码中hidden的id可以用hex解码成Po. 在URL后面输入Po.php得到一个点, 然后不知所措 被水淹没 实际上这里是要遍 ...

  2. 深度剖析前端JavaScript中的原型(JS的对象原型)

          这张图片有点劝退了,哈哈哈~    通过原型机制,JavaScript 中的对象从其他对象继承功能特性:这种继承机制与经典的面向对象编程语言的继承机制不同.本文将探讨这些差别,解释原型链如 ...

  3. Java 多线程--ThreadLocal Timer ExecutorService

    ThreadLocal /** * ThreadLocal:每个线程自身的存储本地.局部区域 * @author xzlf * */ public class ThreadLocalTest01 { ...

  4. vector做形参时的三种传参方式

    vector在做形参的时候传参的方式和普通的变量是一样的,要么传值.要么传引用.要么传指针. 现在分别定义三个以vector为形参的函数: (1) fun1(vector <int> v) ...

  5. 非常简单的string驻留池,你对它真的了解吗

    昨天看群里在讨论C#中的string驻留池,炒的火热,几轮下来理论一堆堆,但是在证据提供上都比较尴尬.虽然这东西很基础,但比较好的回答也不是那么容易,这篇我就以我能力范围之内跟大家分享一下 一:无处不 ...

  6. Python数据分析:大众点评数据进行选址

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:砂糖侠 如果你处于想学Python或者正在学习Python,Pyth ...

  7. ISO及安全业务,机制

    ISO 应用层 为应用软件提供接口,使应用程序能够使用网络服务. 各种应用程序协议如HTTP(Web),Telnet(远程控制),FTP(文本传输) 表示层 数据的交换格式.数据加密解密.数据的压缩解 ...

  8. memcache的缓存原理和应用

    缓存原理 Memcache采用键值对存储方式.它本质是一个大的 hash表,key的最大长度为255个字符,最长过期时间为30天.它的内存模型如下:Memcache预先将可支配的内存空间进行分区(Sl ...

  9. 2019-2020-1 20199308《Linux内核原理与分析》第四周作业

    <Linux内核分析> 第三章 MenuOS的构造 3.1 Linux内核源代码简介 操作系统的"两把宝剑" 中断上下文:保存现场和恢复现场 进程上下文 目录结构 ar ...

  10. Linux安全实验缓冲区溢出

    缓冲区溢出实验: 缓冲区溢出是指程序试图向缓冲区写入超出预分配固定长度数据的情况.这一漏洞可以被恶意用户利用来改变程序的流控制,甚至执行代码的任意片段.这一漏洞的出现是由于数据缓冲器和返回地址的暂时关 ...