HDU5442

HDU5442


做法:把原串复制一份加在后边,中间插特殊入个特殊字符,再把翻转后的串加在后边,同样复制一份。然后做后缀数组,按题意处理细节即可。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <map>
#include <cstring>
#include <cmath>
#include <queue>
#include <set>
#include <vector>
#include <iterator>
#include <string>
#include <deque>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define pb push_back
#define MP make_pair
#define fr first
#define sc second
#define PII pair<int,int>
#define VI vector<int>
typedef long long ll;
typedef unsigned long long ull;
const int N = 100005;
inline int readint() {
    char c=getchar();int x=0,f=1;
    while(!isdigit(c)){if(f=='-')f=-1;c=getchar();}
    while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    return x*f;
}
using namespace std;
int n;
char c[N],str[N];
int rnk[N] , SA[N] , Height[N];
int X[N] , Y[N] , sum[N];
int f[101000][20] , fm[101000][20];
bool cmp(int *r,int a,int b,int l) {
    return ( r[a] == r[b] && r[a+l] == r[b+l] );
}
void calc() {
    int l , p , *x = X , *y = Y , m = 128;
    rep(i,0,m) sum[i] = 0;
    rep(i,1,n) sum[ x[i] = c[i] ] ++;
    rep(i,1,m) sum[i] += sum[i-1];
    per(i,n,1) SA[ sum[ x[i] ]-- ] = i;
    for ( l = 1 , p = 1 ; l <= n ; m = p , l *= 2 ) {
        p = 0;
        rep(i,n-l+1,n) y[++p] = i;
        rep(i,1,n) if ( SA[i] > l ) y[++p] = SA[i] - l;
        rep(i,0,m) sum[i] = 0;
        rep(i,1,n) sum[ x[y[i]] ] ++;
        rep(i,1,m) sum[i] += sum[i-1];
        per(i,n,1) SA[ sum[ x[y[i]] ]-- ] = y[i];
        swap( x , y );
        x[SA[1]] = 1; p = 2;
        rep(i,2,n)
            x[ SA[i] ] = cmp(y,SA[i-1],SA[i],l) ? p - 1 : p++;
    }
    rep(i,1,n) rnk[SA[i]] = i;
    p = 0;
    rep(i,1,n) {
        if ( rnk[i] == 1 ) continue;
        while ( c[i+p] == c[SA[rnk[i]-1]+p] ) p ++;
        Height[rnk[i]] = p;
        if ( p ) p --;
    }
}
void init() {
    n = strlen(str);
    int cc = 0;
    for(int i=0;i<n;++i) c[++cc] = str[i];
    for(int i=0;i<n;++i) c[++cc] = str[i];
    c[++cc] = '$';
    for(int i=n-1;i>=0;--i) c[++cc] = str[i];
    for(int i=n-1;i>=0;--i) c[++cc] = str[i];
    c[cc+1]=0;
    n = cc;
}
int Log[N],rmq[N][30];
void init_rmq() {
    Log[1] = 0;
    for(int i=2;i<=n;++i) Log[i] = Log[i>>1] + 1;
    for(int i=1;i<=n;++i) rmq[i][0] = Height[i];
    for(int j=1;j<=20;++j)
        for(int i=1;i+(1<<(j-1))<=n;++i)
            rmq[i][j] = min(rmq[i][j-1],rmq[i+(1<<j-1)][j-1]);
}
int RMQ_mn(int l,int r){
    int L=Log[r-l+1];
    return min(rmq[l][L],rmq[r-(1<<L)+1][L]);
}
int ask(int x,int y) {
    x=rnk[x],y=rnk[y];
    if(x>y)swap(x,y);
    return RMQ_mn(x+1,y);
}
int T, num;
int biao(int x) {
    if(x <= num) return x;
    return num - (x-num*2-1) + 1;
}
int cal_s(int x) {
    if(x<=num) return 0;
    return 1;
}
int main() {
    scanf("%d",&T);
    while(T--) {
        scanf("%d",&num);
        scanf(" %s",str);
        init();
        calc();
        init_rmq();
        int idx = n;
        int ansb = biao(SA[n]), anss = cal_s(SA[n]);
        for(int i=n;i>=1;--i) if(SA[i]!=num*2+1){
            if(SA[i]<=num) {
                idx = i;
                ansb = biao(SA[i]);
                anss = cal_s(SA[i]);
                break;
            }
            if(SA[i]>=2*num+1&&SA[i]<=3*num+1) {
                idx = i;
                ansb = biao(SA[i]);
                anss = cal_s(SA[i]);
                break;
            }
        }
        for(int i=idx-1;i>=1;--i) if(SA[i] != num*2+1) {
            if(SA[i]>num&&SA[i]<=num*2+1) continue;
            if(SA[i]>3*num+1) continue;
            int lcp = ask(SA[idx],SA[i]);
            if(lcp >= num) {
                int b = biao(SA[i]), s = cal_s(SA[i]);
                if(b<ansb) ansb = b,anss=s;
                else if(b==ansb&&s < anss) ansb=b,anss=s;
            }
        }
        printf("%d %d\n",ansb,anss);
    }
    return 0;
}

posted @ 2018-09-11 00:17  RRRR_wys  阅读(166)  评论(0编辑  收藏  举报