# ABC187 C - 1-SAT

1 min read読了の目安(約1700字 2

ABC187 C - 1-SAT

問題へのリンク

https://atcoder.jp/contests/abc187/tasks/abc187_c

問題概要

N 個の文字列 S_1, S_2, \dots, S_N がある。各文字列は、英小文字の先頭に ! を0文字か1文字付加したものである。

文字列 T は、 T の先頭に ! を0文字付加しても1文字付加しても S_1, S_2, \dots, S_N のいずれかに一致するとき、不満な文字列であるといいます。不満な文字列があるかどうか判定し、あれば1つ示せ。

制約

1 \leqq N \leqq 2 × 10^5
1 \leqq N \leqq 2 × 10^5
1 \leqq |Si| \leqq 10

ABC中の解答

問題のタイトルの SAT とは充足可能性問題 (satisfiability problem, SAT)のことのようだ。

https://ja.wikipedia.org/wiki/充足可能性問題

制約が 1 \leqq N \leqq 2 × 10^5 なので for を2回回していたら TLE になる。比較を早くするためリストではなくセット G に文字 S_i を読むたびに格納していった。比較の条件は

  • S_i の先頭に ! がないなら ! を先頭に足したものと G を比較
  • S_i の先頭に ! があるなら ! を抜いたものと G を比較 (ただし S_i の文字列が2文字以上かも要確認)
    とした。
N = int(input())
G = set([])

for _ in range(N):
    s = input()
    if ('!' + s) in G:
        print(s)
        exit()
    if s[0] == '!' and len(s) >= 2 and s[1:] in G:
        print(s[1:])
        exit()
    G.add(s)
print('satisfiable')

https://atcoder.jp/contests/abc187/submissions/19129922

公式解法1

ABC中の解答では順次文字が追加される度に処理をしていったが、全部の文字列を比較しするとか1つ目の箇条書きだけ考えたらよいとわかる。(!がある方からは見つけられないが、!がない方からは見つけられるので)

したがって、以下のようにシンプルに実装できる。冷静に考えるのが大事だとわかる問題だ。

N = int(input())

S = set(input() for _ in range(N))
for s in S:
    if ('!' + s) in S:
        print(s)
        exit()
print('satisfiable')

https://atcoder.jp/contests/abc187/submissions/19446690

ちなみにセットをリストにするとちゃんと(?)計算コストが高くなり TLE となる。

N = int(input())

S = set(input() for _ in range(N))
for s in S:
    if ('!' + s) in S:
        print(s)
        exit()
print('satisfiable')

https://atcoder.jp/contests/abc187/submissions/19446739