luogu3804 [template] suffix automata

Title link

solution

Use the suffix array to send a suffix automaton template 233

First run through the suffix array to find the height. Then, according to the nature of height, enumerate the positions that contributed, and then look at the minimum value of this position in the longest and longest interval. The answer is \ (len_i * height_i \) . \ (len_i \) means that the longest length of a section of \ (len_i \) \ (height \) has a minimum value of \ (height_i \) . Use monotonic stack statistics.

code

/*
* @Author: wxyww
* @Date:   2020-04-20 07:58:21
* @Last Modified time: 2020-04-20 08:36:41
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<ctime>
using namespace std;
typedef long long ll;
const int N = 1000010;
ll read() {
	ll x = 0,f = 1;char c = getchar();
	while(c < '0' || c > '9') {
		if(c == '-') f = -1; c = getchar();
	}
	while(c >= '0' && c <= '9') {
		x = x * 10 + c - '0'; c = getchar();
	}
	return x * f;
}
char s[N];
int sa[N],height[N],c[N],x[N],y[N],n,m;
void get_sa() {
	for(int i = 1;i <= n;++i) c[x[i] = s[i]]++;
	for(int i = 1;i <= m;++i) c[i] += c[i - 1];
	for(int i = n;i >= 1;--i) sa[c[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;
		for(int i = 1;i <= m;++i) c[i] = 0;
		for(int i = 1;i <= n;++i) ++c[x[i]];
		for(int i = 1;i <= m;++i) c[i] += c[i - 1];
		for(int i = n;i >= 1;--i) sa[c[x[y[i]]]--] = y[i];
		swap(x,y);
		num = 0;
		x[sa[1]] = ++num;
		for(int i = 2;i <= n;++i) {
			if(y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]) x[sa[i]] = num;
			else x[sa[i]] = ++num;
		}
		m = num;
		if(m == n) break;
	}
}
int rk[N];
void get_height() {
	for(int i = 1;i <= n;++i) rk[sa[i]] = i;
	int k = 0;
	for(int i = 1;i <= n;++i) {
		if(rk[i] == 1) continue;
		if(k) --k;
		int j = sa[rk[i] - 1];
		while(j + k <= n && i + k <= n && s[j + k] == s[i + k]) ++k;
		height[rk[i]] = k;
		// printf("%d %d %d\n",i,j,k);
	}
}
int sta[N],top;
int main() {
	// freopen("P3804_1.in","r",stdin);
	scanf("%s",s + 1);
	n = strlen(s + 1);
	m = 'z';
	get_sa();

	get_height();
	// for(int i = 1;i <= n;++i) printf("%d ",height[i]);puts("");

	int ans = 0;
	for(int i = 1;i <= n + 1;++i) {
		while(top && height[i] < height[sta[top]]) {
			ans = max(ans,(i - sta[top - 1]) * height[sta[top]]);
			--top;
		}
		sta[++top] = i;
	}

/*
	for(int r = 1;r <= n;++r) {
		int mn = height[r];
		for(int l = r;l >= 1;--l) {
			mn = min(mn,height[l]);
			ans = max(ans,mn * (r - l + 2));
		}
	}*/

	cout<<ans;
	return 0;
}

Guess you like

Origin www.cnblogs.com/wxyww/p/luogu3804.html