您的位置:首页 > 其它

HDU 5442 Favorite Donut 后缀数组

2016-06-11 13:33 344 查看
题意:

 给你一个甜甜圈,可以正着次也可以反着次求如何按照字典序最大次

后缀数组正反跑一跑就好了

ACcode:

#include <bits/stdc++.h>
#define maxn 20200
using namespace std;
int t1[maxn<<1],t2[maxn<<1],c[maxn<<1];
int r[maxn<<1],sa[maxn<<1],h[maxn<<1],str[maxn<<1];
inline bool cmp(int *r,int a,int b,int l){
return r[a]==r[b]&&r[a+l]==r[b+l];
}
inline void da(int n,int m){
n++;
int *x=t1,*y=t2;
for(int i=0;i<m;++i)c[i]=0;
for(int i=0;i<n;++i)c[x[i]=str[i]]++;
for(int i=1;i<m;++i)c[i]+=c[i-1];
for(int i=n-1;i>=0;--i)sa[--c[x[i]]]=i;
for(int j=1;j<=n;j<<=1){
int p=0;
for(int i=n-j;i<n;++i)y[p++]=i;
for(int i=0;i<n;++i)if(sa[i]>=j)y[p++]=sa[i]-j;
for(int i=0;i<m;++i)c[i]=0;
for(int i=0;i<n;++i)c[x[y[i]]]++;
for(int i=1;i<m;++i)c[i]+=c[i-1];
for(int i=n-1;i>=0;--i)sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=1;
x[sa[0]]=0;
for(int i=1;i<n;++i)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
if(p>=n)break;
m=p;
}
int k=0;
n--;
for(int i=0;i<=n;++i)r[sa[i]]=i;
for(int i=0;i<n;++i){
if(k)k--;
int j=sa[r[i]-1];
while(str[i+k]==str[j+k])k++;
h[r[i]]=k;
}
}
char s[maxn],s1[maxn<<1],s2[maxn<<1];
int pos1,pos2,loop,n;
void doit(){
string a="",b="";
for(int i=0;i<n;++i){
a+=s1[(pos1+i)%n];
b+=s2[(pos2+i)%n];
}
for(int i=2*n;i>1;i--){
if(sa[i-1]>=n) break;
if(h[i]>=n) pos2=sa[i-1];//求反向最大最小下标
}
pos2=n-1-pos2;
pos1++,pos2++;
if(a==b){
if(pos1>pos2) printf("%d 1\n",pos2);
else printf("%d 0\n",pos1);
}
else if(a>b) printf("%d 0\n",pos1);
else printf("%d 1\n",pos2);
}
int main(){
scanf("%d",&loop);
while(loop--){
scanf("%d",&n);
scanf("%s",s);
for(int i=0;i<n;++i)
str[i]=str[i+n]=s1[i]=s1[i+n]=s[i];
str[2*n]=0;
da(n*2,256);
pos1=sa[2*n];
for(int i=n*2-1,k=0;i>=0;--i,++k)
str[k]=s2[k]=s1[i];
da(n*2,256);
pos2=sa[2*n];
doit();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: