Ural1297最長の回文文字列

元の文字列の逆の背後接続元の文字列を考慮した後、セット内の文字ではないとの中間文字で区切られた、我々は、文字列と文字列の前半の後半に対応する各文字の最長の共通のプレフィックスを見つけることができます、答えです。i番目の文字列パリンドロームセンター/文字の右対称軸を考慮した(右フロントハーフ列、文字列を移動に対応した戻って左に相当する)、パリンドローム配列を含む奇数それぞれ/文字の偶数。パリンドローム配列は、文字の奇数が含まれている場合、i番目の文字に対応する文字がN-I + 1であり、長いパリンドローム配列は、LCP(I、N-I +である 1)* 2-1、 パリンドローム配列は、開始位置Iであります-lcp + 1、パリンドローム配列は、文字の偶数を含む場合、i番目の文字に対応する文字がN-I + 2であり、パリンドローム配列は、長LCP(I、N-2 +である 1)* 2、 パリンドローム配列の始まりI-LCP位置。
次の問題は、接尾辞配列と疎テーブルアルゴリズムを使用することができ、迅速な需要LCP(L、R)であります

ZZます。http://blog.sina.com.cn/s/blog_4a0c4e5d01019j35.html

001の#include <cstdioを>
002の#include <CStringの>
003の#include <アルゴリズム>
004名前空間stdを使用。
005 INTのF [4005] [4005]。
006 INTの高さ[4005]。
007 INTランク[4005];
008 INT彼[4005];
009チャーST [4005]。
010 INTのH [4005]。
011 int型N、P、年。
012テンプレート<型名T>
013空隙基数([]、INT Bを[] INT、T S []、INT nは、INT M)
014 {I int型。
015のための(I = 0; I <= M; ++ I)
016 H [I] = 0;
017のための(iは1 =; I <= N; ++ I)
018 ++ H [S [I]]]。
019のための(iは1 =; I <= M; ++ I)
020 H [I] + = H [I-1];
021のための(iはN =、I> 0;  -  I)
022 B [H [S [I]]]  - ] = [I]。
023}
024(init_sa無効)
025 {int型I、J。
026 INTのA [4005]、B [4005]。
027のための(iは1 =; I <= N; ++ I)
028ランク[I] = I。
029基数(ランク、そうST N、256)。
030ランク[1] = 1。
031のための(I = 2、I <= N; ++ I)
032であれば(ST [SA [I-1]]!= ST [SA [I]])
033ランク[I] =順位[[I-1]] + 1。
034他のランク[SA [I] =ランク[SA [I-1]]。
035のための(iは1 =; I <= N; I * = 2)
036 {ため(J = 1; J <= N; ++ j)は
037 {[J] =ランク[J]。
038 IF(I + J <= N)
039 B [J] =順位[I + J]。
040他B [j] = 0;
041 SA [j] = J。
042}
043         radix(sa,rank,b,n,n);
044         radix(rank,sa,a,n,n);
045ランク[1] = 1。
用046(J = 2、J <= N; ++ j)は
047 IF([SA [J-1]!= A [SA [j]] || B [SA [J-1]!= B [SA [j])
048ランク[この[J] =ランク[この[J-1]] + 1。
049他のランク[この[J] =ランク[この[J-1]]。
050 IF(ランク[SA [N]] == N)
051ブレーク。
052}
053}
054無効calc_h()
055 {INT I、P = 0。
056のための(iは1 =; I <= N; ++ I)
057 {(P> 0)であれば
058  -  P;
059(ランク[I]!= 1)の場合
060(ST [I + P] == ST [SA [順位[I] -1] + P])一方
061 ++のp;
062高さ[順位[I] = P。
063}
064}
065無効init_rmq()
066 {int型I、J。
067のための(iは1 =; I <= N; ++ I)
068 F [i]が[0] =高さ[I]。
用069(J = 1;(1 << J)<= N; ++ j)は
用070(I 1 =、I + J-1 <= N; ++ I)
071 F [I] [J] =分(F [I] [J-1]、F [I +(1 <<(j-1))] [J-1])。
072}
073 INTのRMQ(INT L、int型R)
074 {int型のk = 0。
075 IF(L> R)
076スワップ(L、R)。
077((1 <<(k + 1))<= R-L + 1)、一方
078 ++ K;
079リターン分(F [L] [K]、F [R-(1 << K)+1] [K])。
080}
081 INTのLCP(INT L、int型R)
082 {int型A、B。
083 =ランク[L]、B =順位[R]。
084 IF(> B)
085スワップ(B)
086戻りRMQ(+ 1、B)。
087}
088 int型の仕事()
089 {INT I、K。
P = 090年= 1;
091のための(iは1 =; I <= N / 2; ++ I)
092 {K = LCP(I、N-I + 1)。
093(K * 2-1> ANS)場合
094年= K * 2-1、P = I-K + 1。
095 K = LCP(I、N-I + 2)。
096(K * 2> ANS)場合
097年= K * 2、P = IK;
098}
099リターンANS;
100}
主101 INT()
102 {INT I、ANS。
103のscanf( "%s" は、ST + 1)。
104 N = STRLEN(ST + 1)。
105 ST [N + 1] = '#'。
用106(I = N + 2、I <= N * 2 + 1; ++ I)
107 ST [I] = ST [N- +2(中)]。
108 N = N * 2 + 1。
109 init_sa()。
110 calc_h()。
111 init_rmq()。
112のANS =仕事();
113は、(iは、pを=; I <P + ANS; ++ I)
114のprintf( "%のC"、ST [I])。
115のprintf( "\ n");
1

  

おすすめ

転載: www.cnblogs.com/cutemush/p/12343508.html