CODE FESTIVAL 2017 Final B - Palindrome-phobia
備忘録
問題
回答
import sys, os, math, bisect, itertools, collections, heapq, queue # from scipy.sparse.csgraph import csgraph_from_dense, floyd_warshall from decimal import Decimal from collections import defaultdict, deque # import fractions sys.setrecursionlimit(10000000) ii = lambda: int(sys.stdin.buffer.readline().rstrip()) il = lambda: list(map(int, sys.stdin.buffer.readline().split())) fl = lambda: list(map(float, sys.stdin.buffer.readline().split())) iln = lambda n: [int(sys.stdin.buffer.readline().rstrip()) for _ in range(n)] iss = lambda: sys.stdin.buffer.readline().decode().rstrip() sl = lambda: list(map(str, sys.stdin.buffer.readline().decode().split())) isn = lambda n: [sys.stdin.buffer.readline().decode().rstrip() for _ in range(n)] lcm = lambda x, y: (x * y) // math.gcd(x, y) # lcm = lambda x, y: (x * y) // fractions.gcd(x, y) MOD = 10 ** 9 + 7 MAX = float('inf') def main(): if os.getenv("LOCAL"): sys.stdin = open("input.txt", "r") S = iss() cnt = collections.Counter(S) if abs(cnt['a'] - cnt['b']) > 1 or abs(cnt['a'] - cnt['c']) > 1 or abs(cnt['b'] - cnt['c']) > 1: print('NO') else: print('YES') if __name__ == '__main__': main()
考え方
文字列が回文になり得るか否かを判定して回答する。
この問題では使用される文字が'a', 'b', 'c'
の3種類。
この3種類で回文となり得るパターンを考える。
まず、対象が2文字以上のため、2文字から始めると、
'aa', 'bb', 'cc'
の場合。同じ文字が2つ使われている場合には回文となる。
3文字の場合には、
'a〇a', 'b〇b', 'c〇c'
の場合(〇はどの文字でもよい)。
3文字中に1種類の文字が2つ存在している場合には、入れ替えても'aa〇', 'bb〇'
など、
2文字の回文が発生してしまう。
4文字の場合には、
'a〇aa', 'bb〇b', 'cbbc', 'bcbc'
などの場合(〇はどの文字でもよい)。
4文字中に同じ文字が3つまたは2種類が2つずつ存在している場合には、
2文字または3文字の回文が発生してしまう。
これらの条件から各3種類の文字の出現回数に大きな差があると
回文になってしまう箇所が発生していることがわかる。
次に出現回数の差がどの程度あると、回文が発生するかを考える。
2文字の場合、'aa'
を例にすると、
a
の出現回数2, b
の出現回数0, c
の出現回数0と、最大と最小で2
の差がある。
3文字の場合、'aba'
を例にすると、
a
の出現回数2, b
の出現回数1, c
の出現回数0と、こちらも最大と最小で2
の差がある。
逆に、出現回数の差が全て1
以内の文字列では、
'abc', 'abca', 'abcabc', 'abcabca'
など、全て回文を回避することが出来る。
これらの条件から、
3種類の文字の出現回数をカウントし、
最大と最小で、出現回数の差が2
以上存在している場合には回文となり得る箇所がある文字列、
最大と最小で、出現回数の差が1
以下の場合には回文となりえない文字列とわかる。