前缀和(字串查询 Astar 2018 10002)

 

思路:由题目可得,字符串中字典最小的子串单个字符,那么,问题则转化为,在一个字符串中,求字典最小的字符的个数,即区间最值问题,遇到区间问题,我们可以考虑用前缀和。

而题目是要求我们写一个带区间查询功能的算法,且查询次数有一定大小,所以,我们应该让查询的时间复杂度尽量小,这里,我们可以用到前缀和,即先预处理好数据,然后查询的时候直接用

前缀和:

我们先把输入的字符串S进行预处理

那么在这个问题中,如何预处理,才能让区间查询最值速度更快呢?

想法:

求出 S前 n(1,2,3,.....)个字符中每一个字符的个数 k。

即 S[ n ][ char ] = 个数

例如 ABBCACAC

S[1]['A']=1

S[2]['A']=1   S[2]['B']=1

S[3]['A']=1   S[3]['B']=2

S[4]['A']=1   S[4]['B']=2  S[4]['C']=1

.....

那么,求区域  [  L , R ] 各个字符的个数,就可以用 S[ L ][ char ] - S[ R ][ char ] 

再而,S里面的字符字典是按 ascil 排序的,

只要我们用 count = S[ L ][ char ] - S[ R ][ char ] 从A开始记录区间内各个字符的个数(即按字典大小,从小到大记录)

如果 count ≠ 0,当前的 char 就是字典最小的字符,而 count 就是个数

 

代码样例:

#include<iostream>
using namespace std;

const int maxn = 1e5 + 1;
char s[maxn]; //字符串
int map[maxn][91]; // 记录前 n 个字符各个字母的数量

int main() {
	int T, n, q, i, j, t;
	int k, num = 0;
	scanf("%d", &T); // 数据组数
	while (T--) {
		printf("Case #%d:\n", ++num);	
		scanf("%d", &n); //字母总个数
		scanf("%d", &q); //查询次数 

		//初始化 记录表
		for (i = 1; i <= n; i++)
			for (j = 65; j <= 90; j++)
				map[i][j] = 0;

		for (k = 1; k <= n; k++) {
			cin >> s[k];

			for (int t = 65; t <= 90; t++)
				map[k][t] = map[k - 1][t]; // 把第 n-1 行各个字母的个数 更新 到第 n 行

			map[k][s[k]] += 1;
		}

		while (q--) { 
			scanf("%d", &i); // L
			scanf("%d", &j); // R
			for (k = 65; k <= 90; k++) {
				t = map[j][k] - map[i-1][k]; // 区间各个字母的个数
				if (t != 0) { 
					printf("%d\n", t);
					break;
				}
			}
		}
	}
	return 0;
}

 有错误请指出 - -

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值