説明
パリンドローム最長の部分文字列を取得する文字列を入力します。サブストリングを意味することである:連続の元の文字列の文字列セグメント。前方後方見て、プラスと同じように見えます:回文意味があります。アバとyyxyyなど。回文を決定する際に、あなたはすべての句読点とスペースを無視し、大文字と小文字は区別しますが、出力は(ヘッダーとトレーラーの回文配列内の余分な文字を印刷していない)は、無傷のままにしてください必要があります。入力文字列の長さではない以上5000以下、及び単線を占めます。、一番左の出力の開始位置が複数ある場合は最長の回文配列は、出力します。
入力
彼の文字列ではなく、5000以上の文字列の長さ。
出力
回文最長のサブ文字列。
サンプル出力
マダム、私はアダムよ
ヒント
サンプル説明:マダム、私はアダム削除スペース、カンマ、アポストロフィよ、ケースを無視することは、回文で、MADAMIMADAMです。
アルゴリズムの解析I:
まず、「さの判断に句読点、出力を無視するが、Yaoan」問題を解決しますか?簡単な方法を用いることができる:前処理を。オリジナルの句読点が含まれていない新しい文字列、および大文字すべての文字(大文字と小文字の問題を解決する方法を)構築。使用される機能:
0そうでなければ、(1)はisalpha(c)は1文字、返された場合は、文字cかどうかをチェックするために使用されます。
そうでなければ0;数、リターン1と(2)isdigit(c)のCは、数(0〜9)かどうかをチェックするために使用されます。
大文字リターンを対応するC、文字cを大文字に変換するために使用される(3)TOUPPER(C)。
(4)TOLOWER(C)C小文字の文字を変換するために使用され、小文字のリターン対応するC。
のは、開始と終了回文文字列を列挙してみましょう、そしてそれは本当に回文文字列であるかどうかを判断します。
int型の最大値= 0;
用(; I <M; iが0 = I ++)
(; J <M、J ++ J = I)について
IF(S [i..j]是回文串&& J-I + 1> MAX)最大= J-I + 1。
回文の長さを格納し、「現在の最大の」変数maxは、これまでの最長の部分文字列を発見しました。列車は、j番目の文字に対して文字i番目のだ場合パリンドローム配列である(S [i..j]と呼ぶ)、長さがJ-iは、+ 1の最大を超えているかどうかがチェックされます。
次のようにS [i..j]パリンドローム配列のメソッドがあるかどうかを決定します
INT OK = 1;
(; K <= J、K ++、K = I)について
IF(S [K] = S [I + JK]!)OK = 0。
S [k]は、「対称」位置s [I + JK]である限り、比較が失敗したように、フラグが変数OKを0に設定されるべきです。
最後の質問は:出力されます。
評価した最大値以来、私はbufに文字列の元の位置にあるS [i]とS [j]を知っていません。よって、S [i]はPによって[I]でBUF位置セーブ、配列pを大きくする必要があります。前処理で得られ、その後、Pながら、最大の更新[i]とP [J]とX、Y、最終出力BUFに保存[x]は、すべての文字[Y] bufをします。
不十分:列挙があまりにも開始し、サイクルの終わり回文ので、簡単に残業に、長い文字列を入力するとき。
アルゴリズムの解析II:それから「中立」位置Iの回文配列を列挙し、別の文字があるまで出て拡大していきます。ヒント:治療の奇数と偶数の長さは同じではありません。
最終ACコード:
<ビット/ STDC ++ H>の#include の#include <CStringの> 使用して 名前空間STDを、 const int型 MAXN = 5005 ; int型のDP [MAXN] [MAXN]、ハッシュテーブル[MAXN]。 int型のmain(){ ブールフラグ。 int型I、J、L、低、高、 文字列sの、ST; 一方(のgetline(CIN、S)){ ST = "" ; memsetの(ハッシュテーブル、0、はsizeof (ハッシュテーブル))。 memsetの(DP、0、はsizeof(DP))。// 记得初始化 用(iは= 0 ; I <s.size(); I ++ ){ 場合(はisalpha(S [I])){ ST + = TOUPPER(S [I])。 ハッシュテーブル[I] = 1。// 表明是字符 } そう であれば(isdigit(S [I])){ ST + = S [i]は、 ハッシュテーブル[I] = 1 。 } } のためには、(iは= 0 ; I <st.size(); I ++)DP [i]は[I] = 1。// 边界 低い= 0 ; 高い= 0 ; 用(L = 2 ; L <= st.size(); L ++ ){ フラグ = 真。 ための式(I = 0、I + L- 1 <st.size(); I ++ ){ J = I + L - 1 。 // 这里需要注意一下当L == 2时、DP [I + 1] [J-1] == 0 であれば(ST [I] == ST [J] &&(DP [I + 1 ] [J- 1 ] == 1 || L == 2 )){ DP [I] [J] = 1 。 もし(フラグ){ //一度、長さLのパリンドローム配列が更新されて得られた 低= ; I ハイ = ; J でフラグを = falseに ; // 更新されたL個の時間で表さ } } } } のための式(I = 0、J = 0 I <Sであり; .size()&& J <低; Iは++)IF(ハッシュテーブル[I] == 1)J ++; // エンドポイントを見つけ ながら(I <s.size()&&ハッシュテーブル[I] == 0)I ++; // 除去他の文字の前端 のための(; I <s.size()&& J <=高; I ++){ printf(" %のC " 、S [I]); IF(ハッシュテーブル[I] == 1)J ++; // 数、エンドポイントを停止する } のprintf(" \ N- " ); } 戻り 0 ; }
概要:もともとヒントを見ていない、と後で彼らの最初のアイデアと同じアイデアやヒントを見つけました。したがって、この質問、ちょうどその質問に、「アルゴリズム・ノート」に基づいていくつかの条件を追加して、特別な注意コード変数を書いて、間違った操作を行います!