leetcode5最長の回文文字列の動的計画法のManacher

DP

 

 

 

声明のSが空でないないことに注意してください、それに対処

o(n^2)

クラスのソリューション{
 パブリック文字列 longestPalindrome(文字列S){
         場合(s.empty())
             リターン "" ;
        INT LEN = s.length()。
        int型のDP [LEN] [LEN]。
        以下のためにint型 i = 0 ; iがLEN <; I ++ のためのINT K = 0 ; K <LENあり、k ++ 
                DP [I] [K] = 0 ;
        int型開始= 0、終了= 0 ;
        ためにint型 I = 0 ; iがLEN <; Iは++ 
        { 
                DP [i]は[I] = 1 もし((I <len- 1)&&(S [I] == S [iが+ 1 ])){ 
                    DP [I] [I + 1 ] = 1 
                    開始 = I;  = I +は1 ; 
                } 
        } 
        のためのINT DIS = 2 ; DIS <LEN、DIS ++)   //   I-> I-1、I + 1、所以处理不了两个连续
        {
             int型私= 0 ; <LEN)(iはDISを+; iは++ 場合((DP [I + 1 ] [I +ディス1 ] == 1)&&(S [i]が== S [iが+ DISを]))
                { 
                    DP [I] [iが DIS +] = 1 もし((DIS)>(エンド)開始){ 
                        開始 = Iと、
                        エンド =私は+ DISを。
                } 
        } 
        } 
        戻り s.substr(開始、終了スタート+ 1 )。
    } 
}。

 

問題が発生しました: 

= ==書かれました。

そして、最初のMEMなし0アレイをDP ...

 

その後Manacher法

参考https://www.cnblogs.com/mini-coconut/p/9074315.html

まず、Manacherアルゴリズムは巧妙な方法を提供し、パリンドローム配列の長さは、一緒に考慮奇数偶数のパリンドローム配列の長さであり、

実際には、元の文字列の隣り合うの途中でもデリミタを終了する終了を添加しながら通常の状況は、#を使用することができるの下で、デリミタは、元の文字列に表示されるように要求されない、セパレータ内に挿入されます。次に例を示します。

 

(1)レン配列はじめと自然

そのようなTのような長さのパリンドロームTの最長文字列[I]、の中心と補助アレイレン[i]の文字でTと右端の文字Manacherアルゴリズム[I] [i]はバック最長文字の中心として文字列は、T [L、R]、次いでレン[I] = R-I + 1です。

上記の例では、レン[I]配列が誘導されることができます。

 

 

 

 

LENアレイプロパティ有し、LEN [i]が-1長さSの元の文字列でパリンドロームサブストリングであります

証明、

Tは、第1の文字列に変換され、すべての長さがパリンドロームの文字列は、その長さの中心が2 *レン[i]が-1であるようにパリンドロームT [I]における最長文字列を、奇数であり、他の文字より一定数を超えるセパレータの数は、レン[i]は、区切り文字、残りレンがあり、すべてのサブストリングの後、Tはパリンドロームことを確認[I] -1元の文字から文字がストリング、元の文字列の長さのパリンドローム配列がlenになるように、[I] -1。

このプロパティを使用すると、元の問題は、[i]はレンのすべてのために変換されます。ここではどのようにレンの全てを取得する線形時間複雑さの中にあります。

コンピューティング(2)レンアレイ

第1の左から右へ、順次[i]は、算出レン[i]は、レン[J](0 <= jの<i)が算出される場合が完了したレンを算出します。

Pは、最長サブパリンドローム配列の右端の前に計算されてみましょう、と最大位置Poを取得するように構成され、2例:

第一の場合:I <= P

次いで、IセットjのPOに対して対称な位置を見つけ、次にレン[J] <Piの場合、以下に示すように:

 

 

 

 

 

 

次いで、センタリングPO jの内部にその特定のパリンドローム配列はパリンドローム配列を中心とし、iと対称位置のPO上J、

定義された発見回文配列は、順番に、パリンドローム配列または回文配列、

したがって、長さの中心に私は少なくともパリンドローム配列とjが同一の中心であるパリンドローム配列である(Jので、I点P上及びその近傍の対称性、パリンドローム配列対称過去のJ)、即ち、レン[I]> =レン[J]。

レン[J] <Piのため、私がlen [j]が<Pを+ように。対称性は、レンを理解することで、[I] =レン[J]。

 

lenが[J]> =パリンドローム配列を中心とIによって記載対称性によってPiは、Pを越えて延びることができる、そしてPは、我々は一致していない部分よりも大きい場合、位置P + 1から始まりますミスマッチまでの一致が発生し、対応するPO Pとlen [I]を更新します。

 

 

 

 

第二の場合:I> P

私はこの時点で、また、私は回文記載の中点として、全く一致シーケンスPよりも大きくない場合、マッチは、正直でき、マッチングの完了後の位置Pと対応するPOを更新しますそしてレン[I]。

 

 

 

 

2.時間の複雑さの解析

位置マッチングアルゴリズムは、一致を満たしていないだけた場合、既に一致した位置であるため、各位置におけるT文字列のように、アルゴリズムの解析及びZと同様のアルゴリズムのManacher時間複雑さは、もはやのみ、一致しません一致、アルゴリズムの全体的な時間計算量は、実際の長さTは、二回Sとして、時間計算量は依然として線形であるので、N Tは、文字列の長さであるO Manacher(N)です。

アルゴリズムの文字列は1ベースですので、ここではアルゴリズムである、クロスボーダーのPへの更新時間のリードを避けるため、その点に注意してください、我々は、例えば、「$」のために、文字列Tの前に特殊文字を追加します。

書式#include <iostreamの>
書式#include <limits.hに>
書式#include <ベクトル>
名前空間stdを使用。

#define MAX(a、b)は(((A)>(B))は、(a):?(b)参照)
#define分(a、b)は(((A)<(B))(A):(B))

クラスのソリューション{
公:
    文字列longestPalindrome(文字列s)
 {
    文字列manaStr = "$#の";
    //新しい文字列が最初に構築された(;;私はs.sizeを<()は、i ++は、私は0 = INT)について
    {
      manaStr + = S [i]は、
      Mnshtr + = '#';
    }
    ベクター<整数> RD(manaStr.size()、0); //パリンドロームの最大ランレングスを記録する補助アレイと、ここで注意が新しいレコードの長さは、1を減算するストリング、ストリングの元の長さであります
    int型POS = 0、MX = 0; // POSパリンドローム現在最も長い文字列の中間点。最長の現在の文字列の右のエンドポイントパリンドロームをMX
    INT = 0、MAXLEN = 0開始; //開始点、長さを。RD [I]は、上記LEN [I]
    以下のために(int型I = 1; iのmanaStr.sizeを()<;私は++) 
    {
      ?Rdの[I] = iはMX分<(RD [2つの* POS - i]は、MX - I):1; //境界RD [2 * POS-iがLEN [J]であります
      //ことに留意 - ([RD [i]はi]はiはRD [I] <manaStr.size()&& I-RDを[I]> + 0 && manaStrは== manaStrは[iが[i]はRDを+])しながら配列境界の判断
          RD [I] ++;
      右端は、新たに計算されたMXよりも大きい場合(I + RD [I]> MX)//、MXが更新される場合、POS
      {
        POS = I;
        MX = I + RD [I]。
      }
      ( - 1> MAXLEN RD [i])とする場合
      {
        開始=(I - RD [I])/ 2。
        MAXLEN = RD [I] - 1。
      }
    }
    s.substrを返す(、MAXLENを開始)。
  }
}。


(int型ARGC、チャー*のARGV [])INT主
{
    文字列s = "aacdefcaa"。
    
    ソリューションソリューション。
    ストリングRET = solution.longestPalindrome(S)。
    coutの<< RET <<てendl;
    システム(「一時停止」)。
    0を返します。
}

 

おすすめ

転載: www.cnblogs.com/lqerio/p/11723652.html