ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【JSCPC2021】Reverse the String(Lyndon 理论)

2022-01-16 09:31:21  阅读:243  来源: 互联网

标签:tmp long return String int Lyndon IL mod Reverse


传送门

题意

给定字符串 \(s\),问任意翻转一个区间 \([l,r]\) 后得到的最小字符串。

\(\sum |s| \le 1.5\times 10^6\)。

分析

依次考虑答案第 \(i\) 位能否比 \(s_i\)​​ 小可得:\(l\) 一定是右边有字符比它小的最左位置。因此只需考虑翻一个前缀的情况,可以用二分+哈希比较出最小答案,但是有线性做法。

记 \(t=s^R\),我们要把 \(t\) 划分成 \(t_1t_2\),使得 \(t_2t_1^R\) 最小。

直接在 \(t\)​ 上跑 Duval 算法。记当前位为 \(i\)​,和它比较的位为 \(j\)​。当出现 \(t_i<t_j\)​ 时,之前所有整周期内的位置都不可能为 \(t_2\)​​ 的开头,因为严格比不上选 \(i\)​ 所在的半周期的开头,因此可以把整周期丢掉不管。

最终 \(t\) 的剩余部分能划分为 \(w^pw'\) 的形式,其中 \(w\) 为 lyndon 串且 \(w'\) 为 \(w\) 的可空前缀,而 \(t_2\) 的开头一定是某个 \(w\) 或 \(w'\) 的开头。

考虑三个串 \(x,y,z\)​​​​ 且 \(|x|=|y|\)​​​​。那么 \(xzy\)​​​​ 不可能比 \(xxz,zyy\)​ 都小,否则 \(xz>zy\)​​ 和 \(xz<zy\)​ 同时成立导出矛盾。代入 \(x=w^R,y=w,z=w'\)​ 得出答案只能是 \(w'w^{Rp}\)​ 和 \(w^pw'\)​ 之一,比较两种方案的字典序即可。

实现

提交记录

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a),_=(b);i<=_;++i)
#define per(i,a,b) for(int i=(a),_=(b);i>=_;--i)
using namespace std;
typedef long long ll;
typedef unsigned long long ul;
typedef reverse_iterator<int*>RI;
#define pb push_back
#define IL inline
const int mod=998244353;
IL int inc(int x,int y){return x+=y-mod,x+=x>>31&mod;}
IL int dec(int x,int y){return x-=y,x+=x>>31&mod;}
IL int mul(int x,int y){return ul(x)*y%mod;}
IL int idk(int x,int y,int p){return p&1?dec(x,y):inc(x,y);}
IL int ksm(int x,int y,int p=1){
	for(;y;y>>=1,x=mul(x,x))if(y&1)p=mul(x,p);
	return p;
}
//head
const int N=1e5+5;
int T,n,m,mn[N],l;
char s[N],t[N],res[N],tmp[N];
void upd(int r){
	rep(i,1,n+1)tmp[i]=s[i];
	reverse(tmp+l,tmp+r+1);
	if(strcmp(tmp+1,res+1)<0)rep(i,1,n)res[i]=tmp[i];
}
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%s",s+1),n=strlen(s+1);
		mn[n]=s[n]-'a';
		per(i,n-1,1)mn[i]=min(mn[i+1],s[i]-'a');
		l=m=0;
		rep(i,1,n)if(mn[i]<s[i]-'a'){l=i;break;}
		if(!l){puts(s+1);continue;}
		per(i,n,l)t[++m]=s[i];
		rep(i,1,n+1)res[i]=s[i];
		for(int i=2,j=1,k=1;i<=m+1;){
			if(i==m+1){
				upd(n+1-k);
				while(k<j)k+=i-j;
				upd(n+1-k);
				puts(res+1);
				break;
			}
			if(t[i]==t[j]){
				++i,++j;
			}else if(t[i]>t[j]){
				++i,j=k;
			}else{
				while(k<=j)k+=i-j;
				i=j=k,++i;
			}
		}
	}
	exit(0);
}

标签:tmp,long,return,String,int,Lyndon,IL,mod,Reverse
来源: https://www.cnblogs.com/Alfalfa-w/p/15808750.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有