A string exercises

The meaning of problems

Given a string of length n, the requirement will be divided into k sections, which find the longest segment k and lexicographically smallest LCS.

data range

k n 1 e 5 , k \ le n \ le 1e5, | \ sum | lowercase letters

solution

Half + hash + SA

It may first be transformed into the problem and find a lexicographically smallest longest string in the original string without overlapping occurred k times
and half the length l of the string, because the original string of length l is the number of strings O ( n ) O (n) level, the hash value can be calculated for each string, the string is divided into several, for each string calculation is not much overlap occurs most often, and requires determination of two strings lexicographically a pre-SA, and then directly O ( 1 ) O (1) suffix size at the beginning of the two strings are located on it.

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
typedef unsigned long long ull;
const ull step=23,mod=4115188075855873ll;//2^57+1再移除前两位,比较大的模数可以减少hash冲突,毕竟这题不能挂链
inline int read(){
	char c=getchar();int t=0,f=1;
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){t=(t<<3)+(t<<1)+(c^48);c=getchar();}
	return t*f;
}
int n,k;
int x[maxn],y[maxn],sa[maxn],rk[maxn],m=300,t[maxn];
char s[maxn];
void get(){
	for(int i=1;i<=n;i++)t[x[i]=s[i]]++;
	for(int i=1;i<=m;i++)t[i]+=t[i-1];
	for(int i=1;i<=n;i++)sa[t[x[i]]--]=i;
	for(int k=1;k<=n;k<<=1){
		int num=0;
		for(int i=n-k+1;i<=n;i++)y[++num]=i;
		for(int i=1;i<=n;i++)if(sa[i]>k)y[++num]=sa[i]-k;
		memset(t,0,sizeof(t));
		for(int i=1;i<=n;i++)t[x[i]]++;
		for(int i=1;i<=m;i++)t[i]+=t[i-1];
		for(int i=n;i>=1;i--){sa[t[x[y[i]]]--]=y[i];y[i]=0;}
		swap(x,y);x[sa[1]]=1;num=1;
		for(int i=2;i<=n;i++)
		x[sa[i]]=(y[sa[i]]==y[sa[i-1]])&&(y[sa[i]+k]==y[sa[i-1]+k])?num:++num;
		if(num==n)break;
		m=num;
	}
	for(int i=1;i<=n;i++)rk[sa[i]]=i;
}
ull ha[maxn];
int ans;
char alfa[maxn];
typedef pair<ull,int> pii;
pii mp[maxn];
bool calc(int x){
	if(n-x+1<k)return 0;
	memset(ha,0,sizeof(ha));
	ull pre=1;
	for(int i=1;i<x;i++)pre=pre*step%mod;
	for(int i=1;i<=x;i++){
		ha[1]=(ha[1]*step%mod+s[i])%mod;
	}
	for(int i=x+1;i<=n;i++){
		ha[i-x+1]=(ha[i-x]-s[i-x]*pre%mod+mod)%mod;
		ha[i-x+1]=(ha[i-x+1]*step%mod+s[i])%mod;
	}
	int len=n-x+1;
	for(int i=1;i<=n-x+1;i++){
		mp[i]=(pii(ha[i],i));
	}
	sort(mp+1,mp+1+len);
	int lst=1,bt=0,flag=0;
	for(int i=1;i<=len;i++){
		if(mp[i].first!=mp[i+1].first){
			if(i-lst+1>=k){
				int cnt=0,pos=0;
				for(int j=lst;j<=i;j++){
					if(pos<mp[j].second){
						cnt++;
						pos=mp[j].second+x-1;
					}
					if(cnt>=k){
						flag=1;
						if(bt==0||rk[bt]>rk[pos-x+1]){bt=pos-x+1;}
					}
				}
			}
			lst=i+1;
		}
	}
	if(flag&&x>ans)
	for(int i=bt;i<bt+x;i++)alfa[i-bt]=s[i];
	return flag;
}
int main(){
	//freopen("2.in","r",stdin);
	//freopen("2.out","w",stdout);
	n=read(),k=read();
	scanf("%s",s+1);
	get();
	int l=1,r=n;
	while(l<=r){
		int mid=(l+r)>>1;
		if(calc(mid)){ans=mid;l=mid+1;}
		else r=mid-1;
	}
	if(ans){
		puts(alfa);
	}
	else puts("Kyoma is wrong.");
	return 0;
}
Published 62 original articles · won praise 1 · views 982

Guess you like

Origin blog.csdn.net/wmhtxdy/article/details/103891086