欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

CF101532D Couting Test(暴力模拟)

程序员文章站 2022-06-02 22:14:10
...

题面:

Yousef has a string s that is used to build a magical string w by repeating the string s infinitely many times. For example, if s = aabbb , then w = aabbbaabbbaabbbaabbb....

Mohammad always claims that his memory is strong, and that his ability to count is very high, so Yousef decided to hold a test for Mohammad, in order to know the truth of his claims.

Yousef will give Mohammad q queries, such that each query consisting of two integers l and r, and a lowercase English letter c. The answer of each query is how many times the letter c appears between the lth and rth letters in string w.

Mohammad must answer all the queries correctly, in order to proof his claims, but currently he is busy finishing his meal. Can you help Mohammad by answering all queries?

 

Input:

The first line contains an integer T, where T is the number of test cases.

The first line of each test case contains two integers n and q (1 ≤ n ≤ 104) (1 ≤ q ≤ 105), where n is the length of string s, and q is the number of queries.

The second line of each test case contains the string s of length n consisting only of lowercase English letters.

Then q lines follow, each line contains two integers l and r and a lowercase English letter c (1 ≤ l ≤ r ≤ 109), giving the queries.

 

Output:

For each query, print a single line containing how many times the letter c appears between the lth and rth letters in string w.

 

Example:

CF101532D Couting Test(暴力模拟)

 

Note:

As input/output can reach huge size it is recommended to use fast input/output methods: for example, prefer to use scanf/printf instead of cin/cout in C++, prefer to use BufferedReader/PrintWriter instead of Scanner/System.out in Java.

 

分析:

赛中其实想到了主要做法,就是用一个num数组存下当前位置对应字母已经出现了多少次,然后算1-r的出现次数,减去1-l的出现次数,而且奇怪地在这种我一直很迷的边界容易搞不清楚的问题上只改了一次(l--那个地方)就正确了,信心满满地交上去然后TL,哦豁,想到了要做记录来优化,然后!然后!!我竟然想一共会有多少不同字母啊?会把数组开得太大了吧?然后就没有然后了。

结果直到下午补题看到别人的题解我才意识到我这脑袋到底是怎么长的……26个字母啊摔。

做的时候遇到了一个小问题,就是初位置应该从1而不是0开始,这样处理会方便很多,但是cin>>string和%s的方式都让我对怎么把初位置设到1有点迷……然后突然想到可以("%s", &str[1]),顺利解决。

加了记录优化之后竟然还是TL,我就很迷了……改了一些循环的小地方,竟然就AC了,真让人摸不着头脑.jpg

 

AC代码:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 10010;
int t, n, q;
long long l, r, s, e, ans;
char ch, str[maxn];
int num[26][maxn];

int main(){
	cin>>t;
	while(t--){
		cin>>n>>q;
		scanf("%s", &str[1]);
		for(int i = 0; i < 26; i++){
			int temp = 0;
			for(int j = 0; j <= n; j++){
				if(str[j] - 'a' == i) temp++;
				num[i][j] = temp;
				}
		}
			
		while(q--){
			scanf("%lld %lld %c", &l, &r, &ch);
			ans = 0;
			e = s = 0;
			l--;
			
			s = (l / n) * num[ch - 'a'][n] + num[ch - 'a'][l % n];
			e = (r / n) * num[ch - 'a'][n] + num[ch - 'a'][r % n];
			
			ans = e - s;
			printf("%lld\n", ans);
		}
	}
	return 0;
}