社区讨论
求助SA算法
P2870[USACO07DEC] Best Cow Line G参与者 2已保存回复 1
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @lo97yx52
- 此快照首次捕获于
- 2023/10/28 07:03 2 年前
- 此快照最后确认于
- 2023/10/28 07:03 2 年前
这是本人代码,20pts
思路是求出前缀和后缀的SA,贪心暴力扫,如果碰到相同的字母,就比较当前l和r的后缀和前缀
若l后缀小于等于(等号随意取哪边)r的前缀,则选择左边,若r前缀小于l后缀,则选择右边
本人觉得自己做法正确性还有一点玄学,不知是否能被较普遍数据hack,若有错请神仙点出谢谢qwq
code:
CPP#include<bits/stdc++.h>
#define printlf(x) print(x),putchar('\n')
#define printsp(x) print(x),putchar(' ')
using namespace std;
inline int read(){
int x=0;
bool w=0;
char c=getchar();
while(!isdigit(c)) w|=c=='-',c=getchar();
while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48),c=getchar();
return w?-x:x;
}
inline void print(int x){
if(x<0) x=-x,putchar('-');
if(x>9) print(x/10);
putchar('0'+x%10);
}
const int N=5e5+5;
int ans[N],saA[N],saB[N],rkA[N],rkB[N],oldrk[N];
string a="?",b,s;
int n,w,cnt;
inline bool cmpA(int x,int y){
return rkA[x]==rkA[y]?rkA[x+w]<rkA[y+w]:rkA[x]<rkA[y];
}
inline void Get_saA(){求后缀
for(register int i=1;i<=n;++i) saA[i]=i,rkA[i]=a[i];
for(w=1;w<n;w<<=1){
sort(saA+1,saA+1+n,cmpA);
memcpy(oldrk,rkA,sizeof(rkA));
for(register int i=1,p=0;i<=n;++i)
if(oldrk[saA[i]]==oldrk[saA[i-1]] && oldrk[saA[i]+w]==oldrk[saA[i-1]+w]) rkA[saA[i]]=p;
else rkA[saA[i]]=++p;
}
}
inline bool cmpB(int x,int y){
return rkB[x]==rkB[y]?rkB[x+w]<rkB[y+w]:rkB[x]<rkB[y];
}
inline void Get_saB(){//求前缀
for(register int i=1;i<=n;++i) saB[i]=i,rkB[i]=b[i];
for(w=1;w<n;w<<=1){
sort(saB+1,saB+1+n,cmpB);
memcpy(oldrk,rkB,sizeof(rkB));
for(register int i=1,p=0;i<=n;++i)
if(oldrk[saB[i]]==oldrk[saB[i-1]] && oldrk[saB[i]+w]==oldrk[saB[i-1]+w]) rkB[saB[i]]=p;
else rkB[saB[i]]=++p;
}
}
signed main(){
n=read();
for(register int i=1;i<=n;++i){
char ch;cin>>ch;s+=ch;
}
a+=s,b=s+'?';reverse(b.begin(),b.end());
// cout<<a<<endl<<b<<endl;
// cout<<a[0]<<' '<<b[0]<<endl;
Get_saA();
Get_saB();
// cout<<"saA:";
// for(register int i=1;i<=n;++i) cout<<saA[i]<<' ';
// cout<<"\nsaB:";
// for(register int i=1;i<=n;++i) cout<<saB[i]<<' ';cout<<endl;
// cout<<"rkA:";for(register int i=1;i<=n;++i) cout<<rkA[i]<<' ';cout<<endl;
// cout<<"rkB:";for(register int i=1;i<=n;++i) cout<<rkB[i]<<' ';cout<<endl;
int l=1,r=n;
while(l<=r){
if(a[l]<a[r]) ans[++cnt]=l++;
else if(a[l]>a[r]) ans[++cnt]=r--;
else{
if(rkA[l]<=rkB[r]) ans[++cnt]=l++;//上文核心判断
else ans[++cnt]=r--;
}
}
// for(register int i=1;i<=n;++i) cout<<ans[i]<<' ';cout<<endl;
for(register int i=1;i<=cnt;++i)
if(i%80==0)cout<<a[ans[i]]<<endl;
else cout<<a[ans[i]];
return 0;
}
回复
共 1 条回复,欢迎继续交流。
正在加载回复...