首页 > 代码库 > hdu 5008 Boring String Problem(后缀数组)
hdu 5008 Boring String Problem(后缀数组)
题目链接:hdu 5008 Boring String Problem
题目大意:给定一个字符串,初始状态l,r为0,每次询问子串中字典序第l^r^v+1的子串区间,对于重复的输出下标小的。
解题思路:后缀数组,对给定字符串做后缀数组,然后根据height数组确定每个位置做为起点的子串有多少,然后二分查找确定起点位置,但是因为子串的重复的要输出下表小的,所以确定起点后还要确定字典序最小的下标。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long ll;
const int maxn = 1e5+5;
struct Suffix_Arr {
int n, s[maxn];
int SA[maxn], rank[maxn], height[maxn];
int tmp_one[maxn], tmp_two[maxn], c[maxn];
ll sum, num[maxn];
void init (char* str);
int idx(char ch);
void build(int m);
void get_height();
void get_substring();
void query(ll x, ll& L, ll& R);
}AC;
int n;
ll l, r, x;
char str[maxn];
int main () {
while (scanf("%s", str) == 1) {
AC.init(str);
AC.build(27);
AC.get_height();
AC.get_substring();
scanf("%d", &n);
l = r = 0;
while (n--) {
scanf("%I64d", &x);
AC.query((x^l^r) + 1, l, r);
printf("%I64d %I64d\n", l, r);
}
}
return 0;
}
void Suffix_Arr::query(ll x, ll& L, ll& R) {
if (x >= sum) {
L = R = 0;
return;
}
int l = 0, r = n;
for (int i = 0; i < 100; i++) {
int mid = (l + r) / 2;
if (num[mid] < x)
l = mid;
else
r = mid;
}
int len = height[l] + x - num[l], pos = SA[l];
for (int i = l + 1; height[i] >= len && i < n; i++)
pos = min(SA[i], pos);
for (int i = l - 1; height[i+1] >= len && i >= 0; i--)
pos = min(SA[i], pos);
L = pos + 1;
R = pos + len;
}
void Suffix_Arr::get_substring() {
num[0] = 0;
for (int i = 1; i <= n; i++)
num[i] = num[i-1] + (n - 1 - SA[i-1]) - height[i-1];
sum = num[n];
}
void Suffix_Arr::init (char* str) {
n = strlen(str);
for (int i = 0; i < n; i++)
s[i] = idx(str[i]);
s[n++] = 0;
}
int Suffix_Arr::idx(char ch) {
return ch - ‘a‘ + 1;
}
void Suffix_Arr::get_height() {
for (int i = 0; i < n; i++)
rank[SA[i]] = i;
int mv = 0;
for (int i = 0; i < n; i++) {
if (mv) mv--;
if (rank[i] == 0) {
height[0] = 0;
continue;
}
int j = SA[rank[i]-1];
while (s[i+mv] == s[j+mv])
mv++;
height[rank[i]] = mv;
}
}
void Suffix_Arr::build (int m) {
int *x = tmp_one, *y = tmp_two;
for (int i = 0; i < m; i++) c[i] = 0;
for (int i = 0; i < n; i++) c[x[i] = s[i]]++;
for (int i = 1; i < m; i++) c[i] += c[i-1];
for (int i = n - 1; i >= 0; i--) SA[--c[x[i]]] = i;
for (int k = 1; k <= n; k <<= 1) {
int mv = 0;
for (int i = n - k; i < n; i++) y[mv++] = i;
for (int i = 0; i < n; i++) if (SA[i] >= k)
y[mv++] = SA[i] - k;
for (int i = 0; i < m; i++) c[i] = 0;
for (int i = 0; i < n; i++) c[x[y[i]]]++;
for (int i = 1; i < m; i++) c[i] += c[i-1];
for (int i = n - 1; i >= 0; i--) SA[--c[x[y[i]]]] = y[i];
swap(x, y);
mv = 1;
x[SA[0]] = 0;
for (int i = 1; i < n; i++)
x[SA[i]] = (y[SA[i-1]] == y[SA[i]] && y[SA[i-1] + k] == y[SA[i] + k] ? mv - 1 : mv++);
if (mv >= n)
break;
m = mv;
}
}
hdu 5008 Boring String Problem(后缀数组)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。