1. ホーム
  2. python

[解決済み] Pythonで文字列が繰り返されるかどうかを判断するにはどうすればよいですか?

2022-03-15 02:43:09

質問

与えられた文字列が、文字列全体で繰り返されるかどうかをテストする方法を探しています。

[
    '0045662100456621004566210045662100456621',             # '00456621'
    '0072992700729927007299270072992700729927',             # '00729927'
    '001443001443001443001443001443001443001443',           # '001443'
    '037037037037037037037037037037037037037037037',        # '037'
    '047619047619047619047619047619047619047619',           # '047619'
    '002457002457002457002457002457002457002457',           # '002457'
    '001221001221001221001221001221001221001221',           # '001221'
    '001230012300123001230012300123001230012300123',        # '00123'
    '0013947001394700139470013947001394700139470013947',    # '0013947'
    '001001001001001001001001001001001001001001001001001',  # '001'
    '001406469760900140646976090014064697609',              # '0014064697609'
]

は同じことを繰り返す文字列で

[
    '004608294930875576036866359447',
    '00469483568075117370892018779342723',
    '004739336492890995260663507109',
    '001508295625942684766214177978883861236802413273',
    '007518796992481203',
    '0071942446043165467625899280575539568345323741',
    '0434782608695652173913',
    '0344827586206896551724137931',
    '002481389578163771712158808933',
    '002932551319648093841642228739',
    '0035587188612099644128113879',
    '003484320557491289198606271777',
    '00115074798619102416570771',
]

は、そうでないものの例です。

文字列の繰り返し部分はかなり長く、文字列自体も500文字以上になることがあるので、各文字をループしてパターンを作り、パターンと残りの文字列をチェックするのは非常に時間がかかります。これに数百の文字列を掛け合わせると、直感的な解決策は見当たりません。

正規表現を少し調べてみましたが、何を探しているのか、あるいは少なくとも探しているパターンの長さがわかっている場合に適しているようです。残念ながら、私はどちらも知りません。

ある文字列が繰り返されているかどうか、また繰り返されている場合、最短の繰り返しの部分配列は何かを知るにはどうしたらよいでしょうか。

どのように解決するのですか?

正規表現と遅いPythonのループを避ける簡潔な解決策を紹介します。

def principal_period(s):
    i = (s+s).find(s, 1, -1)
    return None if i == -1 else s[:i]

をご覧ください。 コミュニティWikiの回答 ベンチマーク結果については、@davidism が開始しました。まとめると

David Zhangのソリューションが明らかに勝者で、大規模なサンプルセットにおいて他のソリューションの少なくとも5倍の性能を発揮しました。

(この回答は私の言葉ではありません。)

これは、文字列がそれ自身の非自明な回転に等しい場合にのみ周期的であるという観察に基づいている。の最初の出現のインデックスから主要な周期を回復できることに気づいた@AleksiTorhamoに敬意を表します。 s(s+s)[1:-1] と、オプションの startend の引数は、Pythonの string.find .