求助SAM模仿SA 50pts
查看原帖
求助SAM模仿SA 50pts
413065
xiezheyuan楼主2024/6/17 13:24

已经和 @Alex_Wei 题解对拍许多组:

#include <bits/stdc++.h>
#define link __ytxy_ak_ioi
#define CLR(x) memset(x, 0, sizeof(x))
using namespace std;

const int N = 4e5 + 5, M = 10;

int trans[N << 1][M], link[N << 1], len[N << 1], cur, tot, endps[N], siz[N];

void extend(int c, int cnt){
	int x=cur;cur=(++tot);len[cur]=len[x]+1;endps[cnt] = cur;siz[cur] = 1;
	for(;(~x)&&(!trans[x][c]);x=link[x]) trans[x][c] = cur;
	if(!(~x)){link[cur]=0;return;}
	int y=trans[x][c];
	if(len[y]==len[x]+1){link[cur]=y;return;}
	int u=(++tot),d=y;
	link[u]=link[y];link[d]=link[cur]=u;len[u]=len[x]+1;
	for(int i=0;i<9;i++) trans[u][i] = trans[d][i];
	for(;(~x)&&(trans[x][c]==y);x=link[x]) trans[x][c] = u;
}

int n, k;
string s, s1;
bool vis[N << 1];
int lft[N << 1], rnk[N], rktt;
int son[N << 1], rev[N << 1], seg[N << 1], top[N << 1], sgtt = 1, dep[N << 1];
vector<int> ptr[N << 1];
vector<int> zyb[N << 1];

void count_siz(int u){
	for(int v : ptr[u]){
		count_siz(v);
		siz[u] += siz[v];
	}
}

int dfs1(int u){
	int szt = 1, tmp = 0;
	son[u] = 0;
	for(int v : ptr[u]){
		dep[v] = dep[u] + 1;
		int szv = dfs1(v);
		szt += szv;
		if(tmp < szv){
			tmp = szv;
			son[u] = v;
		}
	}
	return szt;
}

void dfs2(int u){
	if(son[u]){
		top[son[u]] = top[u];
		seg[son[u]] = ++sgtt;
		rev[sgtt] = son[u];
		dfs2(son[u]);
	}
	for(int v : ptr[u]){
		if(son[u] == v) continue;
		top[v] = v;
		seg[v] = ++sgtt;
		rev[sgtt] = v;
		dfs2(v);
	}
}

int find(int l, int r){
	int u = endps[r];
	while(true){
//		cout << u << ' ';
		if(!top[u] || len[link[top[u]]] < (r - l + 1)){
			int L = seg[top[u]], R = seg[u];
			while(L <= R){
				int mid = (L + R) >> 1;
                if(!(~link[rev[mid]])){
                    L = mid + 1;
                    continue;
                }
				if(len[link[rev[mid]]] < (r - l + 1)) L = mid + 1;
				else R = mid - 1;
			}
			L--;
//			cout << rev[L] << '\n';
			return rev[L];
		}
		u = link[top[u]];
	}
}

int length;

void dfs(int u){
	sort(ptr[u].begin(), ptr[u].end(), [&](int x, int y){
		return s1[lft[x] - 1] < s1[lft[y] - 1];
	});
	if(length <= len[u] && length > len[link[u]]){
		int rkt = rktt + 1;
		for(int i : zyb[u]){
			rnk[i] = rkt;
			rktt++;
		}
		return;
	}
	for(int v : ptr[u]) dfs(v); 
}


bool check(int x, bool dbg = 0){
	for(int i=1;i<=length;i++){
		int now = 0;
		for(int j=1;j<=k;j++){
			int p = (i + now - 1) % n + 1;
			if(rnk[p] <= x) now += length;
			else now += length - 1;
		}
//		if(dbg){
//			cout << '\n';
//		}
		if(now >= n) return true;
	}
	return false;
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> k >> s;length = (n - 1) / k + 1;
	s1 = s + s;reverse(s1.begin(), s1.end());link[0] = -1;
	for(unsigned i=0;i<s1.size();i++) extend(s1[i] - '0' - 1, i + 1);
	for(unsigned i=1;i<=n;i++){
		int LFT = 0;
		for(int j=endps[i];j;j=link[j]){
			LFT += (len[j] - len[link[j]]);
			lft[j] = LFT;
			if(vis[j]) break;
			vis[j] = true;
		}
	}
	for(int i=1;i<=tot;i++) ptr[link[i]].push_back(i);
	count_siz(0);
	seg[0] = dep[0] = 1;top[0] = len[0] = 0;
	dfs1(0);dfs2(0);
	for(int i=1;i<=n;i++){
		int revt = i + length - 1;
		if(revt > n) revt -= n;
		revt = n - revt + 1;
		int u = find(i, i + length - 1);
//		cout << u << ' ' << len[u] << ' ' << len[link[u]] << '\n';
		zyb[find(i, i + length - 1)].push_back(revt);
	}
//	cout << "------------------------------------\n";
	dfs(0);
//	for(int i=1;i<=rktt;i++) cout << rnk[i] << ' ';cout<<'\n';
//	cout << "------------------------------------\n";
	int L = 1, R = n;
	while(L < R){
		int mid = (L + R) >> 1;
		if(check(mid)) R = mid;
		else L = mid + 1;
	}
	reverse(s1.begin(), s1.end());
//	cout << L << ' ' << check(L) << '\n';
//	check(L, 1);
	int fir = 0;
	for(int i=1;i<=n;i++){
		if(rnk[i] == L){
			fir = i;
			break;
		}
	}
//	cout << fir << '\n';
	for(int i=0;i<length;i++) cout << s1[(fir + i - 1)];
	return 0;
}

/*
10 9
4363593573
*/

/*
7 5
7183782
*/
2024/6/17 13:24
加载中...