文字列が回文の連結であるかどうかをチェックするアルゴリズムはありますか?


9

文字のシーケンスが回文の連結であることを確認する線形時間アルゴリズムはありますか?私の頭に浮かぶのは、単純な解決策だけです。

1. k = 1
2. Split string into k substrings (all possibilities) and check
3. k++
4. repeat

注:長さ1の文字列が回文であると定義されている場合、答えは自明です。これはそうではないと仮定しましょう。


14
長さ1のささいなパリンドロームを許可する場合(たとえば、文字列 "a"はパリンドロームです)、すべての文字列はパリンドロームの連結です。
Matt Lewis、

それは有用ですか、それとも演習ですか?
Jan Hudec 2013

@MattLewisパリンドロームの数を最小限に抑えることができます。Jan、なぜ?動的プログラミングのいい練習のようですね。
–PålGD

1
@ハイレ号。ばらばらの回文のみ。
saadtaame 2013

1
Norvigはパリンドロームについて広範囲にわたる研究を行いました。このページに興味がある可能性があります:norvig.com/palindrome.html
robowolverine

回答:


7

ばらばらのパリンドロームが必要だとすると、これはPALSTAR問題と呼ばれ、Zvi GalilとJoel Seiferasによる線形時間アルゴリズムがあります。「Palstar」の線形時間オンライン認識アルゴリズム

アルゴリズムの説明は、テキストアルゴリズム (リンク先のページと前のページを参照)の本にあります。

2次時間アルゴリズムで問題がなければ、単純な動的プログラミングが機能するようです。

文字列を指定すると、をパリンドロームに分解できるかどうかを示す配列を維持します。s[1,n]s[1,j]

また、が回文かどうかを示す2Dテーブルも保持しています。これは、中心を選択して2つのポインターを外側に移動し、その中心の回文をチェックすることにより、時間で構築できます。考えられる中心ごとにこれを行います。中心は、それぞれ時間を要します。s[i,j]O(n2)Θ(n)O(n)

これで、が分解できるかどうかを確認できますごとにが分解できるかどうかを確認し、はパリンドロームです(上記の2Dテーブルを使用)。これにより、時間および空間アルゴリズムが生成されます。s[1,j+1]1ij1s[1,i]s[i+1,,j+1]Θ(n2)Θ(n2)

Manacherのオンラインアルゴリズムを使用してが回文であるかどうかを計算する場合、スペースの使用量は下げることができます(がから進むにつれて) 、基本的に2Dテーブルを削除します。s [ i + 1 j + 1 ] i j 1 1O(n)s[i+1,j+1]ij11


これは私のアルゴリズムに似ていますが、前処理の部分を説明してOPに任せただけではありませんが、なぜ誰も私のアルゴリズムを気にしなかったのかわかりません:)

@SaeedAmiri:線形時間に言及する私の回答の最初の部分を読んだことがありますか?どのように似ていますか?ところで、OPは質問を線形時間アルゴリズムを求めるように変更しました。これにより、あなたの答えがわかり、私の答えの後半は無関係になります。動的プログラミングアルゴリズムがO(n)スペースのみを使用するようにする(そして前処理ステップを取り除く)Manacherのアルゴリズムについて言及したかったので、私は私の回答からその部分を削除しませんでした、そしてそれはまだ他の人々に関係があるかもしれませんたまたまこの質問に出くわす
Aryabhata 2013

シリーズは使わないでください。それは冗談です。私はあなたの答えがおおむね好きです。OPが私の解決策を理解できなかったため、英語の文章に問題があると思います。 。しかし、良い点OPは最近彼の質問を変更しました、そしてManacherのアルゴリズムに似た解決策があるかもしれません(しかし、本当に簡単ではありません)。

1
@SaeedAmiri:なるほど、心配はいりません:-)
Aryabhata

3

オーバーラップが許可されている場合、線形時間(入力文字列のサイズ)で実行できます。

いくつかの定義

最大パリンドロームの概念を定義しましょう:

半径kの最大のパリンドロームストリングSのサブストリングS」というものです

  • 中心から始めて、S 'は両方向に同じk文字を読み取ります
  • ただしk + 1文字は不可
  • k> 1(したがって、単一の文字は回文ではありません)

たとえば、の場合S = bananaS' = ananaは半径2の最大回文です。

最大のパリンドロームは、いくつかのkの半径kの最大パリンドロームです。

例えば、場合S = banana"ana""anana"、そのすべての最大の回文です。

最大パリンドロームの使用

ここで、文字列のすべての最大パリンドロームを見つけることができれば、文字列全体がパリンドロームの連結であるかどうかを確認するのは簡単です。

取るS = abbaccazayaz。その最大の回文は次のとおりです。

  • アバ、位置2と3の中央、半径= 2
  • acca、位置5と6の間の中央、半径= 2
  • 位置10を中心とするzayaz、半径= 2

したがって、「abba」は[1..4]を超え、「acca」は[4..7]を超え、「zayaz」は[8..12]を超えます。この3つのパリンドロームの連結(オーバーラップは許可されますか?)はストリング全体に及ぶため、 "abbaccazayaz"はパリンドロームの連結になります。

線形時間での最大パリンドロームの計算

これで、文字列Sのすべての最大パリンドロームを線形時間で見つけることができることわかりました*

アイデアは、一定時間の最も低い共通の祖先クエリを備えたSのサフィックスツリーを使用することです

したがって、長さmの文字列SがO(n)時間の回文の連結であるかどうかを確認できます。

* Gusfield、Dan(1997)、「9.2すべての最大パリンドロームを線形時間で見つける」、文字列、ツリー、シーケンスのアルゴリズム


knanaanana

「アナナ」のものを編集していただき、ありがとうございます。また、OPは最小パリンドロームシーケンスを要求しません。単一の文字が回文ではない場合、入力文字列がパリンドロームの連結であるかどうかを判断するだけです。
Haile

1
k=1

1
@Khaur間隔がソートされていない場合のみ、対数線形時間がかかります。この場合、おそらくそうです。
Yuval Filmus、2013

1
質問へのコメントで、OPは、パリンドロームの重複は許可されないことを明示的に追加しています。したがって、現在の形のこのソリューションは、OPが求めているものではありません。このソリューションは、いくつかの考えとせいぜい2次の複雑さで、重複しないケースも解決するように変更できると思います。しかし、私はそれについてあまり考えていません。
Paresh 2013

2

Palindrome [] []が配列で、Palindrome(i、j)がiからjまでの部分文字列が回文であるかどうかをチェックし、回文である場合に1を返すか、回文でない場合に無限大を返し、最小の数を探す関数であるとします。パーティションの場合、ボトムアップで作成します。

Palindrome[i][i]=1.
0i<j<n:Palindrome[i][j]=min{Palindrome(i,j),minik<j{Palindrome[i,k]+Palindrome[i+1,k]}}

セルを埋める必要があり、各セルは最大で使用するため、アルゴリズムは。少し変更(前処理)すると、に改善できます。また、このパーティションを見つけることは難しくありません。O n O n 3O n 2O(n2)O(n)O(n3)O(n2)


例で説明できますか?説明:abbaaccaabba.
saadtaame 2013

@ saadtaame、OK、ここでは(cs.stackexchangeで)テーブルを作成することはできません。または、これを行う方法が見つからなかったため、どこかでこれを行い、後で画像をここに配置します。しかし今のところ、自分で理解しようとし、長さ1の部分文字列から始めて、長さ2のパリンドロームをチェックします。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.