0w1

TIOJ 1276 . 對稱之山 (Mountain) ( Z-value Palindrome )

1276 - 對稱之山 (Mountain) | TIOJ INFOR Online Judge
題意:
求最長回文子字串長度
題解:
同學縮隨便 dp 就可以過了 ??!!!
本來要寫 SA ( N lg N ),想想有 codebook 就寫 O( N ) 的 SA
拿出 codebook 後看到這個 完全不知道在幹麻就 AC惹

後注:
可以用哈希解決,理論上會過但TLE。
先塞無限大包住所有原本的數字,免去處理基偶回文問題。接著枚舉中央點,二分搜左右最長可以延伸到哪裡。

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef vector< int > vi;
typedef vector< vi > vvi;
typedef vector< ll > vl;
typedef vector< vl > vvl;
typedef pair< int, int > pii;
typedef vector< pii > vp;

const int MAXL = 1e7 + 2;

int len, sel;
int s[ MAXL * 2 ], se[ MAXL * 2 ];
int pal[ MAXL * 2 ];

int g[ MAXL ];

const int INF = 0x3f3f3f3f;

void genpal(){
    int i, j, r, t;
    sel = 2 * len + 1;
    for(i=0;i<sel;i++) se[i]=(i&1)?s[i>>1]:INF; pal[0]=0;
    j=r=0;
    for(i=1;i<sel;i++) {
        t=min(r>=i?pal[2*j-i]:0,r-i+1);
        for(;i-t>=0&&i+t<sel;t++) if(se[i-t]!=se[i+t]) break; pal[i]=--t;
        if(i+t>r) { r=i+t; j=i; }
    }
}

void init(){
    scanf( "%d", &len );
    for( int i = 0; i < len; ++i )
        scanf( "%d", s + i );
    genpal();
    int maxv = 0;
    for( int i = 1; i < sel; ++i )
        maxv = max( maxv, pal[ i ] );
    printf( "%d\n", maxv - 1 );
}

void solve(){

}

signed main(){
    ios::sync_with_stdio( false );
    init();
    solve();
    return 0;
}
// hash
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef vector< int > vi;
typedef vector< vi > vvi;

const int INF = 0x3f3f3f3f;

template< class T1, class T2 >
int upmax( T1 &x, T2 v ){
    if( x < v ){
        x = v;
        return 1;
    }
    return 0;
}

const int bsz = 2; // number of hashes = base size
const int MOD[] = { ( int ) 1e9 + 7, ( int ) 1e9 + 9 };
const int BASE[] = { ( int ) 3e5 + 1, ( int ) 3e5 + 7 };

int N;
vi A;

void init(){
    cin >> N;
    A = vi( N );
    for( int i = 0; i < N; ++i )
        cin >> A[ i ];
}

int get_hash( const vvi &phash, const vvi &fbase, int ver, int ql, int qr ){ // [ ql, qr )
    int f = fbase[ ver ][ qr - ql ];
    int res = phash[ ver ][ qr ] - 1LL * phash[ ver ][ ql ] * f % MOD[ ver ];
    res %= MOD[ ver ], res += MOD[ ver ], res %= MOD[ ver ];
    return res;
}

void solve(){ // finds longest palindrome
    vi s( 2 * N + 1 );
    for( int i = 0; i < 2 * N + 1; ++i )
        s[ i ] = ( ~i & 1 ) ? INF : A[ i >> 1 ];
    vi rs = s; reverse( rs.begin(), rs.end() );

    vvi fbase( bsz, vi( s.size() + 1 ) );
    vvi shash( bsz, vi( s.size() + 1 ) );
    vvi rshash( bsz, vi( s.size() + 1 ) );
    for( int i = 0; i < bsz; ++i ){
        fbase[ i ][ 0 ] = 1;
        for( int j = 0; j + 1 <= s.size(); ++j )
            fbase[ i ][ j + 1 ] = 1LL * fbase[ i ][ j ] * BASE[ i ] % MOD[ i ],
            shash[ i ][ j + 1 ] = ( 1LL * shash[ i ][ j ] * BASE[ i ] + s[ j ] ) % MOD[ i ],
            rshash[ i ][ j + 1 ] = ( 1LL * rshash[ i ][ j ] * BASE[ i ] + s[ s.size() - j - 1 ] ) % MOD[ i ];
    } // shash[ 0 ] = s[ 0 ], shash[ 1 ] = s[ 0 ] * BASE + s[ 1 ], ...

    int ans = -1;
    for( int i = 1; i + 1 < s.size(); ++i ){
        int lb = 0, rb = min( i, ( int ) s.size() - i - 1 );
        while( lb <= rb ){
            int mid = lb + rb >> 1;

            int ok = 1;
            for( int t = 0; t < bsz; ++t ){
                int ri = s.size() - i - 1;
                if( get_hash( shash, fbase, t, i - mid, i )
                 != get_hash( rshash, fbase, t, ri - mid, ri ) ){
                    ok = 0;
                    break;
                }
            }

            if( ok )
                ans = max( ans, mid * 2 + 1 ),
                lb = mid + 1;
            else
                rb = mid - 1;
        }
    }
    cout << ans / 2 - 1 << endl;
}

signed main(){
    ios::sync_with_stdio( 0 );
    cin.tie( 0 ), cout.tie( 0 );
    init();
    solve();
    return 0;
}