Pythonで2つの文字列をアナグラムのペアになるように分割するプログラム
同じ長さを持つ2つの空でない文字列 s と t が与えられたとします。これらを部分文字列に分割し、s と t の各ペアが同じサイズで、互いにアナグラム(並べ替え語)となるようにします。そのうえで、s と t を最大回数カットできるような切り分け位置(インデックス)を求めます。条件を満たす結果が存在しない場合は、空のリストを返します。
例えば、入力が s = "bowcattiger"、t = "owbactietgr" の場合、出力は [0, 3, 5, 6, 10] となります。これは、文字列を5つの区間に分割でき、それぞれの対応する部分文字列が互いにアナグラムになっているためです。具体的には、s = ["bow", "ca", "t", "tige", "r"]、t = ["owb", "ac", "t", "ietg", "r"] と分割されます。
解法のアプローチ
この問題を解くためには、以下の手順に従います。
- intervals := 新しいリストを作成する
- cs := 文字列 s に含まれる各文字とその出現頻度を記録したマップ(Counter)を作成する
- ct := 文字列 t に含まれる各文字とその出現頻度を記録したマップ(Counter)を作成する
- もし cs と ct が等しくない場合(全体としてアナグラムになっていない場合)は、
- 空のリストを返す
- x を s の長さ - 1 から 0 まで逆順にループさせる:
- cs[s[x]] の値を 1 減らす
- ct[t[x]] の値を 1 減らす
- もしこの時点で cs と ct が等しければ、
- x を intervals の末尾に追加する
- intervals をソートして返す
このアルゴリズムのポイントは、右端から順に文字を「取り除いて」いき、そのたびに残りの部分の文字頻度マップが一致するかどうかを確認することです。一致した時点が、有効な切り分け境界となります。Counter 同士の比較は O(1) 相当で行えるため、全体の計算量は O(n) 程度で効率的に処理できます。
理解を深めるために、以下の実装例をご覧ください。
実装例
from collections import Counter
class Solution:
def solve(self, a, b):
intervals = []
ca = Counter(a)
cb = Counter(b)
if ca != cb:
return []
for x in reversed(range(len(a))):
ca[a[x]] -= 1
cb[b[x]] -= 1
if ca == cb:
intervals.append(x)
return sorted(intervals)
ob = Solution()
s = "bowcattiger"
t = "owbactietgr"
print(ob.solve(s, t))入力
"bowcattiger", "owbactietgr"
出力
[0, 3, 5, 6, 10]
-
【Python】文字列として表現された2つの数値を加算して文字列で返す方法
2つの文字列 S と T が与えられ、それぞれが整数を表しているとします。この2つの数値を加算し、その結果を同じく文字列として返す必要があります。 例えば、入力が 256478921657 と 5871257468 の場合、出力は 262350179125 になります。これは、256478921657 + 5871257468 = 262350179125 となるためです。 解決の手順 この問題は、以下のステップで解決できます。 S と T を文字列から整数に変換する 2つの整数を加算する(ret = S + T) 結果の ret を文字列に変換して返す Pythonでは int() 関数
-
【Python入門】2つの文字列から珍しい単語(ユニークな単語)を見つけるプログラムの作り方
はじめに この記事では、以下の問題文に対する解決方法を、実際のコード例とともにわかりやすく解説します。 問題文 2つの文字列が与えられたとき、その中から「珍しい単語」(どちらか一方の文字列にしか出現しない単語)をすべて抽出することを目標とします。両方の文字列に共通して含まれる単語は除外します。 解決のアプローチ ここでは辞書(dict)を使った出現回数のカウント方式を採用します。手順は次のとおりです。 空の辞書を用意する 各文字列をsplit()で単語ごとに分割する 各単語の出現回数を辞書に記録する 出現回数がちょうど1回の単語だけを結果として返す 実装例 # 珍しい単語を見つける関