第一周训练:I

I

You want to perform the combo on your opponent in one popular fighting game. The combo is the string s consisting of n lowercase Latin letters. To perform the combo, you have to press all buttons in the order they appear in s. I.e. if s=“abca” then you have to press ‘a’, then ‘b’, ‘c’ and ‘a’ again.

You know that you will spend m wrong tries to perform the combo and during the i-th try you will make a mistake right after pi-th button (1≤pi<n) (i.e. you will press first pi buttons right and start performing the combo from the beginning). It is guaranteed that during the m+1-th try you press all buttons right and finally perform the combo.

I.e. if s=“abca”, m=2 and p=[1,3] then the sequence of pressed buttons will be ‘a’ (here you’re making a mistake and start performing the combo from the beginning), ‘a’, ‘b’, ‘c’, (here you’re making a mistake and start performing the combo from the beginning), ‘a’ (note that at this point you will not perform the combo because of the mistake), ‘b’, ‘c’, ‘a’.

Your task is to calculate for each button (letter) the number of times you’ll press it.

You have to answer t independent test cases.

Input
The first line of the input contains one integer t (1≤t≤104) — the number of test cases.

Then t test cases follow.

The first line of each test case contains two integers n and m (2≤n≤2⋅105, 1≤m≤2⋅105) — the length of s and the number of tries correspondingly.

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

The third line of each test case contains m integers p1,p2,…,pm (1≤pi<n) — the number of characters pressed right during the i-th try.

It is guaranteed that the sum of n and the sum of m both does not exceed 2⋅105 (∑n≤2⋅105, ∑m≤2⋅105).

It is guaranteed that the answer for each letter does not exceed 2⋅109.

Output
For each test case, print the answer — 26 integers: the number of times you press the button ‘a’, the number of times you press the button ‘b’, …, the number of times you press the button ‘z’.

Input
3
4 2
abca
1 3
10 5
codeforces
2 8 3 2 9
26 10
qwertyuioplkjhgfdsazxcvbnm
20 10 1 2 3 5 10 5 9 4

Output
4 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 9 4 5 3 0 0 0 0 0 0 0 0 9 0 0 3 1 0 0 0 0 0 0 0
2 1 1 2 9 2 2 2 5 2 2 2 1 1 5 4 11 8 2 7 5 1 10 1 5 2

The first test case is described in the problem statement. Wrong tries are “a”, “abc” and the final try is “abca”. The number of times you press ‘a’ is 4, ‘b’ is 2 and ‘c’ is 2.

In the second test case, there are five wrong tries: “co”, “codeforc”, “cod”, “co”, “codeforce” and the final try is “codeforces”. The number of times you press ‘c’ is 9, ‘d’ is 4, ‘e’ is 5, ‘f’ is 3, ‘o’ is 9, ‘r’ is 3 and ‘s’ is 1.

思路:正常做一个一个加会超时,所以采用了别的方式

比如第一个用例:4 , 2 , abca , 1 , 3
记录对应数字的次数,此例子中每个数字都出现了一次,然后将数组排序,开始从左向右遍历数组,第一个为1,则第一个字母应该加上2次(因为一共有2个数字,都包含了1,,即大于等于1的都包含了一个1),第二个数字为3,然后从第二个字母开始到数字3,即第三个字母处,就应该加上1(因为3后边有0个数字,即共有1个2,一个3)。。。。
但实际写代码过程中进行了一些小处理,我将数组长度多定义一个长度,然后最后一个位置放上字符串长度,这样就不用再统一加一了。

import java.util.Arrays;
import java.util.Scanner;

public class I {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int t= sc.nextInt();
		for (int i = 0; i < t; i++) {
			int m = sc.nextInt();
			int n = sc.nextInt();
			sc.nextLine();
			String str  = sc.nextLine();
			int[] arr = new int[n+1];
			arr[n] = m;//最后一项等于总长度m
			int[] count = new int[m+1];//记录数字出现的个数的数组,数字范围1~m
			count[m]++;//数字m次数加一
			for (int j = 0; j < n; j++) {
				arr[j] = sc.nextInt();
				count[arr[j]]++;//对应的数字次数加一
			}
			Arrays.sort(arr);
			int[] help = new int[m];//记录每位应该加几的数组,长度为字符串长度m
			int index = 0;//记录上次加完数后的末尾
			int cnt = 0;//记录遍历arr数组的下标
			for (int j = 1; j < count.length; j++) {
				if(count[j] >= 1) {
					for (int j2 = index; j2 < arr[cnt]; j2++) {
						help[j2] = (n+1);//改位应该加几次
					}
					n -= count[j];
					if(n == -1) break;
					index = arr[cnt];
					cnt+=count[j];//arr数组下标加上该数出现的次数
				}
			}
			int[] res = new int[26];
			for (int j = 0; j < help.length; j++) {
				res[str.charAt(j) - 97] += help[j];
			}
			for (int j = 0; j < res.length; j++) {
				System.out.print(res[j]+" ");
			}
			System.out.println();
		}
		sc.close();		
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我已经记录下来了您的问题。针对您的问题,可以使用以下代码实现手写体数字图片的识别和分类系统。代码如下: ```python import os import cv2 import numpy as np import matplotlib.pyplot as plt # 1. 下载emnist数据集 # 2. 解压emnist数据集 # 3. 拆分目录,将数字1的图片放在1目录里 for i in range(10): path = './emnist/train/{}'.format(i) if not os.path.exists(path): os.makedirs(path) with open('./emnist/train.csv') as f: f.readline() for line in f: line = line.strip().split(',') label, img = int(line[0]), np.array(line[1:], dtype=np.uint8) if label == i: cv2.imwrite(path + '/{}.jpg'.format(line[0]), img.reshape(28, 28)) # 4. Png图片转换为jpg图片 def png2jpg(png_path): img = cv2.imread(png_path, cv2.IMREAD_UNCHANGED) if img.shape[2] == 4: alpha_channel = img[:, :, 3] _, mask = cv2.threshold(alpha_channel, 1, 255, cv2.THRESH_BINARY) color = img[:, :, :3] img = cv2.bitwise_not(cv2.bitwise_not(color, mask=mask)) else: img = cv2.bitwise_not(cv2.bitwise_not(img)) return img for i in range(10): path = './emnist/train/{}'.format(i) for img_name in os.listdir(path): if img_name.endswith('.png'): img_path = os.path.join(path, img_name) img = png2jpg(img_path) cv2.imwrite(os.path.join(path, img_name.replace('.png', '.jpg')), img) # 5. 反色转换为白底黑字 for i in range(10): path = './emnist/train/{}'.format(i) for img_name in os.listdir(path): img_path = os.path.join(path, img_name) img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE) img = 255 - img cv2.imwrite(img_path, img) # 6. 去除不合理的数据 for i in range(10): path = './emnist/train/{}'.format(i) for img_name in os.listdir(path): img_path = os.path.join(path, img_name) img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE) if np.sum(img) < 1000: os.remove(img_path) ``` 这段代码可以实现手写体数字图片的预处理,包括将PNG图片转换为JPG图片、将黑底白字转换为白底黑字、去除不合理的数据等操作。接下来,您可以使用预处理后的数据训练模型进行手写数字图片的识别和分类。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值