您的位置:首页 > 理论基础 > 计算机网络

hdu 5442 长春区域赛网络赛 1006 Favorite Donut(后缀数组)

2015-09-13 15:50 561 查看

题目链接:

hdu 5442

题目大意:

给出一个环,每颗珠子有一个甜度,选择第一个珠子和吃的方向,问得到的吃珠子的字符串的字典序最大的,如果有多个,选取位置最靠前的,如果还是多个,选择顺时针吃的。

题目分析:

-首先构造一个字符串,首先正着按环吃,那么就是字符串正着写两遍,连接在一起;中间用没有出现过的字符连接,然后逆时针吃的,也就是反着写两遍连在一起。

- 然后我们找到后缀排序前面与排序第一个的公共前缀大于等于n的所有的情况,然后寻找他们当中符合题意的字符串的即可。起始位置可以通过suffix数组得到。

AC代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 200007
int wwa[maxn],wwb[maxn],wwv[maxn],wws[maxn];
int cmp(int *r,int a,int b,int l){
    return r[a]==r[b]&&r[a+l]==r[b+l];
}

void da(int *r,int *sufix,int n,int m){
    int i,j,p,*x=wwa,*y=wwb,*t;
    for(i=0;i<m;i++)wws[i]=0;
    for(i=0;i<n;i++)wws[x[i]=r[i]]++;
    for(i=1;i<m;i++)wws[i]+=wws[i-1];
    for(i=n-1;i>=0;i--)sufix[--wws[x[i]]]=i;
    for(j=1,p=1;p<n;j*=2,m=p){
        for(p=0,i=n-j;i<n;i++)y[p++]=i;
        for(i=0;i<n;i++)
            if(sufix[i]>=j)
                y[p++]=sufix[i]-j;
        for(i=0;i<n;i++)wwv[i]=x[y[i]];
        for(i=0;i<m;i++)wws[i]=0;
        for(i=0;i<n;i++)wws[wwv[i]]++;
        for(i=1;i<m;i++)wws[i]+=wws[i-1];
        for(i=n-1;i>=0;i--)
            sufix[--wws[wwv[i]]]=y[i];
        for(t=x,x=y,y=t,p=1,x[sufix[0]]=0,i=1;i<n;i++)
            x[sufix[i]]=cmp(y,sufix[i-1],sufix[i],j)?p-1:p++;

    }
    return;
}
int r[maxn];
int rank1[maxn],height[maxn],sufix[maxn];
void calheight(int *r,int *sufix,int n){
    int i,j,k=0;
    for(i=0;i<=n;i++) rank1[sufix[i]]=i;
    for(i=0;i<n;height[rank1[i++]]=k)
        for(k?k--:0,j=sufix[rank1[i]-1];r[i+k]==r[j+k];k++);
    return;
}
struct Node{
    int p,c;
};
int comp(Node a,Node b){
    if(a.p == b.p) return a.c < b.c;
    return a.p < b.p;
}

Node ans[maxn];

char word[maxn];

int main(){
    int t,n;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        scanf("%s",word);
        for(int i = 0;i < n; i++){
            r[i]=r[i+n] = word[i];
        }
        int len =n*4+1;
        r[n*2] = '#';
        for(int i = 0;i < n; i++){
            r[i+n*2+1] = r[i+n*3+1] = word[n-i-1];
        }
        r[len] = 0;
        da(r,sufix,len+1,328);
        calheight(r,sufix,len);
        int cnt = 0;
        ans[cnt++].p = sufix[len];
        for(int i = len-1;i > 1; i--){
            if(height[i+1] < n) break;
            if(sufix[i]>=n&&sufix[i]<=n*2) continue;
            if(sufix[i]>=n*3+1)continue;
            ans[cnt++].p = sufix[i];
        }
        for(int i = 0;i < cnt; i++){
            if(ans[i].p > 2*n){
                ans[i].c =1;
                ans[i].p = n-(ans[i].p-2*n-1);
            }
            else {
                ans[i].p++;
                ans[i].c =  0;
            }
        }
        sort(ans,ans+cnt,comp);
        printf("%d %d\n",ans[0].p,ans[0].c);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: