【NOIP2018复习】字串数量(思考)

1186.字串数量

时间限制:20000MS内存限制:256000KB

题目描述

有一个由大写字母组成的长度为n的字符串,每次询问l,r,需要回答有多少个非空子串是l到r这个子串里面字典序最小的。这里的非空子串是字符串中由至少一个位置连续的字符组成的子序列,两个子串是不同的当且仅当这两个子串内容不完全相同或者出现在不同的位置。比如"AA" 的字典序比 "AAA" 小,"AB" 的字典序比 "AC" 小。
 

输入

第一行包含一个整数 T,表示有 T 组测试数据。
接下来依次描述 T 组测试数据。对于每组测试数据:
第一行包含两个整数 n 和 q,表示字符串的长度以及询问的次数。
第二行包含一个长为 n 的只包含大写英文字母的字符串
接下来 q 行,每行包含两个整数l,r

输出

对于每组测试数据,输出q 行,每行包含一个整数,表示l到r这个子串中字典序最小的子串个数,行末不要有多余空格。

输入样例复制

1
2 3
AB
1 1
1 2
2 2

输出样例复制

1
1
1

说明

30%数据满足 T<=1,n<=1e3, q<=1e5 70% T<=2, n<=1e5, q<=1e5 100% T<=2, n<=1e6, q<=1e6 注意优化输入输出 

题解:仔细审题,题目即求区间内最小字母的个数,对每种字母做前缀和,统计时找到最小的数量不为0的字母即可
 

 

const

  maxn=1000000;

var

  a:array[1..maxn]of char;

  sum:array['A'..'Z',0..maxn]of longint;

  i,l,r,n,t,q,kk:longint;

  j:char;

procedure init;

var

  i:longint;

  j:char;

begin

  readln(n,q);

  for i:=1 to n do

  begin

    read(a[i]);

    for j:='A' to 'Z' do

      sum[j,i]:=sum[j,i-1];

    sum[a[i],i]:=sum[a[i],i]+1;

  end;

end;

begin

  readln(t);

  for kk:=1 to t do

  begin

    init;

    for i:=1 to q do

    begin

      readln(l,r);

      for j:='A' to 'Z' do

        if sum[j,r]-sum[j,l-1]>0 then

        begin

          writeln(sum[j,r]-sum[j,l-1]);

          break;

        end;

    end;

  end;

end.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值