質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1315閲覧

正規表現を使ったアプローチについて

退会済みユーザー

退会済みユーザー

総合スコア0

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2017/11/21 01:27

プログラミング初学者です

https://www.hackerrank.com/challenges/re-findall-re-finditer/problem

例えばこの問題を解こうとしたときに

python

1import re 2m = re.findall(r'[^aiueoAIUEO][aiueoAIUEO]{2,}[^aiueoAIUEO]', input()) 3if len(m) == 0: 4 print("-1") 5else: 6 for i in m: 7 print(i[1:-1]) 8

まずこのようなコードで解けると思ったのですが、これだと例えば
abaabaabaabaae
のように探したい文字列が連続したときに後の文字列がアウトプットされないという問題があります

また、同様に
https://www.hackerrank.com/challenges/the-minion-game/problem
この問題を正規表現を使って解けないかと考えたのですが(discussionをチラッと見ると全然使ってはいなかったのですが)、最小単位でfindallを使っても、特定の文字列が見つかると次の文字を読み込んでしまい組み合わせは読み込めないという問題があります

python

1import re 2 3print(re.findall(r'[^AIUEO]+?', input())) 4 5>>['B', 'N', 'N']

正規表現を使うときに、組み合わせをすべて上手く読み取れるようなアプローチがあれば教えていただきたいです
よろしくお願いします

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

前半については、すべての母音以外の文字を2つに繰り返してから、findallすればよいかと。
もっとスマートな方法はある可能性が高いですが。

python

1import re 2s = input() 3cs = set(re.findall(r'[^aiueoAIUEO]', s)) 4for c in cs: 5 s = s.replace(c, c*2) 6m = re.findall(r'[^aiueoAIUEO][aiueoAIUEO]{2,}[^aiueoAIUEO]', s) 7if len(m) == 0: 8 print("-1") 9else: 10 for i in m: 11 print(i[1:-1])

こっちのほうが速いですね。

python

1import re 2s = input() 3s = re.sub(r'[^aiueoAIUEO]{1,}', 'zz', s) 4m = re.findall(r'[^aiueoAIUEO][aiueoAIUEO]{2,}[^aiueoAIUEO]', s) 5if len(m) == 0: 6 print("-1") 7else: 8 for i in m: 9 print(i[1:-1])

後半は、ただの数え上げなので、正規表現を使わないかと。
例えば、A***なら[A, A*, A**, A***]4種類を数え上げるだけなので。
どうしても全パターンを一度出力したいのならitertoolsのcombinationsを使えば良いです。

python

1import itertools 2 3def list_of_combs(s): 4 combs = [s[i:j] for i,j in itertools.combinations(list(range(len(s)))+[None], 2)] 5 return combs 6 7print(list_of_combs(input())) 8#['B', 'BA', 'BAN', 'BANA', 'BANAN', 'BANANA', 'A', 'AN', 'ANA', 'ANAN', 'ANANA', 'N', 'NA', 'NAN', 'NANA', 'A', 'AN', 'ANA', 'N', 'NA', 'A']

以下チラ裏かもですが。
アルゴリズムに興味があるのかわからないのですが、全パターンを一度展開してしまうと、計算時間・計算メモリともに厳しいものがあります。
計算時間としては計算のオーダーが重要かと思います。

  1. 上の例で、A***を見たら直ちにそれは4を足せば良いと分かればオーダーは文字列の長さにかかわらず1となります。O(1)と表記します。
  2. それに対して[A, A*, A**, A***]と展開すると、文字列の長さM個だけ増えます。これはO(M)というやつです。

この外側に、上の問題の場合文字列の先頭を走査するのに、Sの長さN回行う必要があります。

  1. それぞれの部分文字列の数え上げがO(1)であれば、全体でO(N)、
  2. 部分文字列の数え上げがO(N)であれば、全部合わせて数え上げるのにO(N^2)の計算量がかかります。

問題ではSの長さの上限が10^6でしたので、O(N)のアルゴリズムでは10^6回、O(N^2)のアルゴリズムでは10^12回演算が発生します。
高性能なCPUでも4.5GHzなどなので一秒あたり10^9の演算しかできません。
比較してみると前者のアルゴリズムでは1秒以内に終わるのに対して、後者のアルゴリズムでは数分かかります。

投稿2017/11/21 02:54

編集2017/11/21 06:47
mkgrei

総合スコア8560

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問