tookunn’s diary

主に競技プログラミング関係

CODE FESTIVAL 2014 予選B C 錬金術師

解法

まずS1,S2,S3のそれぞれのアルファベットの出現回数を数えておく。
その出現回数をそれぞれA1,A2,A3とする。

S3を作れる場合は、S3に出現するアルファベットは必ずS1またはS2から使われるので、
S1から使われる回数は最低でも、0回かA3 - A2回のどちらか大きい方。
(S1に対象のアルファベットが存在しない場合は0回、
A3の方がA2より大きい場合は残りの回数はA1で補わなきゃいけないので最低でもA3 - A2回)

S1から使われる回数は最大でもA1回かA3回のどちらか小さい方。
(A1をすべて使う場合はA1回、A1をすべて使い切らなくてもA3回補える場合はA3回)

最終的に、Nの値が最低でもS1から使わなきゃいけない回数以上で最高でS1から使える回数以下だった場合はS3を作れる。

参考:CODE FESTIVAL 予選B 解説

ソースコード

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.NoSuchElementException;

public class Main {
	String s1,s2,s3;
	int[] a1,a2,a3;
	int N,N2;
	
	
	public void solve() {
		s1 = next();
		s2 = next();
		s3 = next();

		a1 = new int[26];
		a2 = new int[26];
		a3 = new int[26];

		N2 = s3.length();
		N = N2 / 2;

		//それぞれのアルファベットの出現数を記録
		for(int i = 0;i < N2;i++){
			a1[s1.charAt(i) - 'A']++;
			a2[s2.charAt(i) - 'A']++;
			a3[s3.charAt(i) - 'A']++;
		}

		int m = 0;
		int low = 0;

		for(int i = 0;i < 26;i++){

			//そのアルファベットがs1から使われる一番少ない回数
			int min = Math.max(0, a3[i] - a2[i]);

			//そのアルファベットがs1から使われる一番多い回数
			int max = Math.min(a1[i], a3[i]);

			//min回からmax回まで使えるので、余分に使える回数を求める
			m += max - min;
			
			low += min;
		}

		//low = 必ず使わなきゃいけない回数
		//m = 余分に使える回数
		
		//Nの値が必ず使わなきゃいけない回数以上で
		//必ず使わなきゃいけない回数 + 余分に使える回数以下の場合
		if(low <= N && N <= low + m){
			out.println("YES");
		}else{
			out.println("NO");
		}




	}

	public static void main(String[] args) {
		out.flush();
		new Main().solve();
		out.close();
	}

	/* Input */
	private static final InputStream in = System.in;
	private static final PrintWriter out = new PrintWriter(System.out);
	private final byte[] buffer = new byte[2048];
	private int p = 0;
	private int buflen = 0;

	private boolean hasNextByte() {
		if (p < buflen)
			return true;
		p = 0;
		try {
			buflen = in.read(buffer);
		} catch (IOException e) {
			e.printStackTrace();
		}
		if (buflen <= 0)
			return false;
		return true;
	}

	public boolean hasNext() {
		while (hasNextByte() && !isPrint(buffer[p])) {
			p++;
		}
		return hasNextByte();
	}

	private boolean isPrint(int ch) {
		if (ch >= '!' && ch <= '~')
			return true;
		return false;
	}

	private int nextByte() {
		if (!hasNextByte())
			return -1;
		return buffer[p++];
	}

	public String next() {
		if (!hasNext())
			throw new NoSuchElementException();
		StringBuilder sb = new StringBuilder();
		int b = -1;
		while (isPrint((b = nextByte()))) {
			sb.appendCodePoint(b);
		}
		return sb.toString();
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public double nextDouble() {
		return Double.parseDouble(next());
	}
}