AcWing 3325. Kick_Start c++和java实现

18 篇文章 0 订阅
17 篇文章 0 订阅

题目

Ksenia 非常喜欢读书,因此每天她都会从自己最喜欢的书中选取一段内容进行阅读,然后再开始她早晨的其他活动。

一段内容可以看作是整个文本中的一个子字符串。

Ksenia 有点迷信,她坚信如果阅读的这段内容是以字符串 KICK开头,然后中间包含 0 个或更多个字符,最后以字符串 START结尾,即使这段内容没什么意义,她的一天也会非常的幸运。

给定这本书的全部文本内容,请你数一数在这本书变得破旧不堪,Ksenia 不得不再买新书之前,共有多少个幸运片段可供她阅读。

只要两个片段的起始位置或结束位置不同,就认为这两个片段是不同的,即使它们包含的内容完全相同。

还需注意,不同片段之间可能会有重叠部分。

输入格式
第一行包含整数 T,表示共有 T 组测试数据。

每组数据共一行,包含一个仅由大写字母构成的字符串 S。

输出格式
每组数据输出一个结果,每个结果占一行。

结果表示为 Case #x: y,其中 x 为组别编号(从 1 开始),y 为幸运片段的数量。

数据范围
1 ≤ T ≤ 100,
1 ≤ |S| ≤ 105

输入样例:

3
AKICKSTARTPROBLEMNAMEDKICKSTART
STARTUNLUCKYKICK
KICKXKICKXSTARTXKICKXSTART

输出样例:

Case #1: 3
Case #2: 0
Case #3: 5

解题思路

题目要求求 “KICK” 和 “START” 的对的数量,且必须 “KICK” 在前,“START” 在后;

  1. 对于每个 “START” ,只有在 “START” 前的 “KICK” 才能与之配对,且配对数量等于该 “START” 前的 “KICK” 的数量,即每遇到一个 “KICK”,“KICK”计数加一;
  2. “KICK” 和 “START” 的对的数量只需要将每个 “START” 可以配对的数量进行加总即可,即每遇到一个 “START” ,就在总数上加上当前位置前的 “KICK” 数;
  3. 查找 “KICK” 和 “START” 可以直接调用 substr() 函数或使用字符数组每位进行对比;
  4. 注意:“KICK” 末位的 “K” 也可以作为 “KICK” 的首位,所以当遇到 “KICK” 跳过部分字符时,不可以将末位的 “K” 跳过。

AC代码

Java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

public class Main {
	
	public static void main(String[] args) throws IOException {
		InputReader in = new InputReader(System.in);
		PrintWriter out = new PrintWriter(System.out);
		
		int t = in.nextInt();
		
		int res = 0;	// 当前的“KICK”“START”对的数量
		int cnt = 0;	// 当前位置前的“KICK”数量
		char[] ch;
		
		for(int i = 1; i <= t; i++) {
			ch = in.next().toCharArray();
			
			res = 0;
			cnt = 0;
			
			for(int j = 0; j + 4 < ch.length; j++) {
				if(ch[j] == 'K' && ch[j + 1] == 'I' && ch[j + 2] == 'C' && ch[j + 3] == 'K') {
					cnt++;	// 当前位置前的“KICK”数量加一
					j += 2;	// 因为末位也是‘K’,所以只需后移两位
				}
				else if(ch[j] == 'S' && ch[j + 1] == 'T' && ch[j + 2] == 'A' && ch[j + 3] == 'R' && ch[j + 4] == 'T') {
					res += cnt;	// 当前的“START”一共能和“KICK”组成 cnt 对
					j += 4;
				}
			}
			
			out.println("Case #" + i + ": " + res);
		}
		
		out.flush();
	}
	
	public static class InputReader {
		BufferedReader reader;
		StringTokenizer tokenizer;
		
		public InputReader(InputStream in) {
			reader = new BufferedReader(new InputStreamReader(in));
		}
		
		public String next() throws IOException {
			while(tokenizer == null || !tokenizer.hasMoreTokens()) {
				tokenizer = new StringTokenizer(reader.readLine());
			}
			return tokenizer.nextToken();
		}
		
		public int nextInt() throws IOException {
			return Integer.parseInt(next());
		}
	}

}

c++

#include<bits/stdc++.h>

using namespace std;

int main()
{
    int t = 0;
    cin >> t;

    string s;

    int res = 0;    // 当前的“KICK”“START”对的数量
    int cnt = 0;    // 当前位置前的“KICK”数量

    for(int i = 1; i <= t; i++)
    {
        cin >> s;

        res = 0;
        cnt = 0;

        for(int j = 0; j + 4 < s.size(); j++)
        {
            if(s.substr(j, 4) == "KICK")
            {
                cnt++;  // 当前位置前的“KICK”数量加一
                j += 2; // 因为末位也是‘K’,所以只需后移两位
            }
            else if(s.substr(j, 5) == "START")
            {
                res += cnt; // 当前的“START”一共能和“KICK”组成 cnt 对
                j += 4;
            }
        }

        cout << "Case #" << i << ": " << res << endl;
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值