最小距离查询
时间限制 1000 ms 内存限制 65536 KB
题目描述
给定一个由小写字母 a 到 z 组成的字符串 S,其中第 i 个字符为 S[i](下标从 0开始)。你需要完成下面两个操作:
INSERT c 其中 c 是一个待输入的字符。你需要在字符串的末尾添加这个字符。保证输入的字符同样是 a 到 z 之间的一个小写字母。
QUERY x 其中 x 是一个输入的整数下标。对于这个询问,你需要回答在 S 中和 S[x]相等且与 x 最近的距离。输入保证 x 在当前字符串中合法
例如 S = “abcaba”,如果我们操作:
INSERT a
则在 S 的末端加一个字符 a,S 变成"abcabaa"。
接下来操作
QUERY 0
由于 S[0] = a,在 S 中出现的离他最近的 a 在下标为 3 的位置上,距离为 3 - 0 = 3。因此应当输出 3。
接下来,如果
QUERY 4
S[4] = b,S 中离它最近的 b 出现在下标为 1 处,距离为 4 - 1 = 3。同样应当输出 3。
给定初始字符串 S 和若干操作,对于每个 QUERY,你需要求出相应的距离。
HINT 由于输入数据较大,C/C++中推荐使用 scanf 进行读入以获得更快的读入速度。同时请注意算法复杂度。
输入格式
输入的第一行是一个正整数 T(T≤20),表示测试数据的组数。
每组输入数据的第一行是一个初始串 S。第二行是一个正整数
m(1≤m≤100000),表示总共操作的数量。接下来 m 行,每行表示一个操作。操作的格式如上所述。
数据保证在任何情况下,S 的长度不会超过 100000。
输出格式
对于每个 QUERY,输出所求的最小距离。如果 S 中其它位置都不存在和它相同的字符,输出-1。
输入样例
2
axb
3
INSERT a
QUERY 0
QUERY 1
explore
3
INSERT r
QUERY 7
QUERY 1
输出样例
3
-1
2
-1
思路
这道题抽象一下变成,有一个字符数组
a[i] = [a,c,c,e,p,t,e,p]
对于每一个a[i]如何求出a[j]使得a[i] = a[j]且 a[i] a[j]距离最近(左右连个方向)
暴力
每一次查找,从x往左循环遍历到起点找到第一个与a[x]相等的元素,下标为left,往右循环遍历到终点找到第一个与a[x]相等的元素,下标为right,根据left和right的情况输出
时间复杂度为0(n) n为字符串长度
题目已知n = 10e6 输入规模m = 10e6,最终的时间复杂度达到了O(n*m),达到了10e12,肯定超时
所以必须想办法优化查询到O(1)
空间换时间
lr[i][0]
记录下标为i的元素的左边与它相同且距离最近的元素的距离
lr[i][1]
记录下标为i的元素的左边与它相同且距离最近的元素的距离
pre[k]
记录最近上一次出现k的下标
a[i] = [a,c,c,e,p,t,e,p]
假设插入e
,此时上一次出现e
的下标为3(pre['e'-'a'] = 3
),这时候只需要更新e
C++
#include"iostream"
#include"cstring"
using namespace std;
const int N = 100005;
int T;
int lr[N][2],idx;
int cnt[26],pre[26];
void insert(char x){
int k = x - 'a';
cnt[k]++;
if(cnt[k] >= 2){
lr[pre[k]][1] = lr[idx][0] = idx - pre[k];
}
pre[k] = idx;
idx++;
}
int query(int x){
int l = lr[x][0];
int r = lr[x][1];
if(l == 0 && r == 0){
return -1;
}else if(l != 0 && r != 0){
return min(l,r);
}else{
return max(l,r);
}
}
void init_lr(string s){
for(int i = 0; i < s.size(); i++){
insert(s[i]);
}
}
int main(){
cin >> T;
while(T--){
memset(lr,0,sizeof lr);
memset(cnt,0,sizeof cnt);
memset(pre,-1,sizeof pre);
idx = 0;
string s;
cin >> s;
init_lr(s);
int n;
cin >> n;
while(n--){
string op;
cin >> op;
if(op == "INSERT"){
char x;
cin >> x;
insert(x);
}else{
int x;
cin >> x;
cout << query(x) << endl;
}
}
}
}