列表

详情


NC217868. 小丑生产值

描述

Garakuta Doll Play

给定字符串 ,这个字符串被称为「小丑」,并进行  次询问。
每次询问给定 ,问这个字符串所有与  相交且长度大于一的整循环子串中字典序最小的一个。这个字符串称为「小丑生产值」。

 表示将  从左往右第  到第  个字符顺次连接得到的字符串。
称  是整循环串当且仅当  存在循环节(若不存在长度小于 的循环节视为不存在)且  的最小循环节  满足 

输入描述

第一行,一个字符串 
第二行,一个正整数 
以下  行,每行一个正整数 

输出描述

对于每个操作,输出所求的「小丑生产值」在  中第一次出现的左右端点。
不存在则输出一行一个 

示例1

输入:

acacabab
4
2
3
5
7

输出:

1 4
1 4
5 8
5 8

示例2

输入:

abcd
2
1
2

输出:

-1
-1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 421ms, 内存消耗: 44684K, 提交时间: 2021-06-06 14:42:34

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 500005;
int n, m;
char s[maxn];
#define ull unsigned long long
const int seed = 19491001;
ull hs[maxn], pw[maxn];
inline ull get(int l, int r) {
	return hs[r] - hs[l - 1] * pw[r - l + 1];
}
int getlcs(int i, int j) {
	int l = 1, r = min(i, j), res = 0;
	while(l <= r) {
		int mid = (l + r) >> 1;
		if(get(i - mid + 1, i) == get(j - mid + 1, j))
			res = mid, l = mid + 1;
		else
			r = mid - 1;
	}
	return res;
}
int getlcp(int i, int j) {
	int l = 1, r = n - max(i, j) + 1, res = 0;
	while(l <= r) {
		int mid = (l + r) >> 1;
		if(get(i, i + mid - 1) == get(j, j + mid - 1))
			res = mid, l = mid + 1;
		else
			r = mid - 1;
	}
	return res;
}
bool cmp(int l1, int r1, int l2, int r2) {
	int len = getlcp(l1, l2);
	if(len >= min(r1 - l1 + 1, r2 - l2 + 1))
		return r1 - l1 < r2 - l2;
	return s[l1 + len] < s[l2 + len];
}
void init_hs() {
	pw[0] = 1;
	for(int i = 1; i <= n; i++) {
		pw[i] = pw[i - 1] * seed;
		hs[i] = hs[i - 1] * seed + s[i];
	}
}
int rt[maxn];
void lyndon() {
	static int st[maxn], top;
	top = 0;
	for(int i = n; i >= 1; i--) {
		st[++top] = i;
		while(top > 1 && cmp(i, st[top], st[top] + 1, st[top - 1]))
			top--;
		rt[i] = st[top];
	}
}
int len[maxn];
vector<int> ins[maxn];
vector<int> del[maxn];
void modify(int l, int r, int p) {
	ins[l].push_back(p);
	del[r + 1].push_back(p);
}
void find_runs() {
	for(int i = 1; i <= n; i++) {
		int p = rt[i] - i + 1;
		int L = i - getlcs(i - 1, rt[i]), R = rt[i] + getlcp(i, rt[i] + 1);
		if(R - L + 1 >= p * 2) 
			modify(L, R - p * 2 + 1, p);
	}
}
void init_runs() {
	init_hs();
	lyndon();
	find_runs();
	for(int i = 1; i <= n; i++)
		s[i] = 'a' + (25 - (s[i] - 'a'));
	lyndon();
	find_runs();
	for(int i = 1; i <= n; i++)
		s[i] = 'a' + (25 - (s[i] - 'a'));
}
int ans[maxn];
int main() {
	scanf("%s%d", s + 1, &m);
	n = strlen(s + 1);
	init_runs();
	
	multiset<int> s;
	for(int i = 1; i <= n; i++) {
		for(auto u : ins[i])
			s.insert(u);
		for(auto u : del[i])
			s.erase(s.find(u));
		if(s.size())
			len[i] = *s.begin();
	}
	
	for(int i = 1; i <= n; i++) {
		ans[i] = ans[i - 1];
		if(len[i] && (!ans[i] || cmp(i, i + len[i] * 2 - 1, ans[i], ans[i] + len[ans[i]] * 2 - 1)))
			ans[i] = i;
	}
	for(int i = 1, x; i <= m; i++) {
		scanf("%d", &x);
		if(ans[x])
			printf("%d %d\n", ans[x], ans[x] + len[ans[x]] * 2 - 1);
		else
			puts("-1");
	}
	return 0;
}

上一题