【LOJ】#3103. 「JSOI2019」节日庆典

LOJ#3103. 「JSOI2019」节日庆典

能当最小位置的值一定是一个最小后缀,而有用的最小后缀不超过\(\log n\)

为什么不超过\(\log n\)个,看了一下zsy的博客。。

假如\(i = AAB\)\(j = AB\)\(B\)\(A\)的一个严格前缀,\(|j| < |i| < 2|j|\)

但是有\(k = B\),导致了若\(j\)\(i\)优,则\(k\)会比\(j\)优,\(j\)\(k\)优,则\(i\)会比\(j\)优,那么\(j\)就没用了

然后取这\(\log\)里最大的就是一段后缀和开头比较,可以预处理出每个串和开头的lcp,用扩展kmp

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define ba 47
#define MAXN 5005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    while(c < '0' || c > '9') {
	if(c == '-') f = -1;
	c = getchar();
    }
    while(c >= '0' && c <= '9') {
	res = res * 10 +c - '0';
	c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
	out(x / 10);
    }
    putchar('0' + x % 10);
}
char s[3000006];
int L,lcp[3000006];
bool cmp(int l0,int r0,int l1,int r1) {
    if(r0 < l0) return true;
    if(r1 < l1) return false;
    int l = min(lcp[l0],min(r1,r0 - l0 + 1));
    if(s[l0 + l] <= s[l1 + l]) return true;
    return false;
}
void Solve() {
    scanf("%s",s + 1);
    L = strlen(s + 1);
    lcp[1] = L;int p = 0,r = 0;
    for(int i = 2 ; i <= L ; ++i) {
	int t = 0;
	if(r >= i) t = min(r - i + 1,lcp[i - p + 1]);
	while(i + t <= L && s[t + 1] == s[i + t]) ++t;
	lcp[i] = t;
	if(r < i + t - 1) {p = i;r = i + t - 1;}
    }
    vector<int> f;f.clear();
    for(int i = 1 ; i <= L ; ++i) {
	vector<int> g;g.clear();g.pb(i);
	for(auto t : f) {
	    while(g.size() && s[t + i - g.back()] < s[i]) g.pop_back();
	    if(g.size() == 0 || s[t + i - g.back()] == s[i]) {
		while(g.size() && i - t + 1 <= 2 * (i - g.back() + 1)) g.pop_back();
		g.pb(t);
	    }
	}
	f = g;
	int res = f[0];
	for(int j = 1 ; j < f.size() ; ++j) {
	    if(cmp(f[j] + i - res + 1,res - 1,1,res - f[j] - 1)) res = f[j];
	}
	out(res);space;
    }
    enter;
}
int main(){
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
}
posted @ 2019-06-12 19:56  sigongzi  阅读(444)  评论(0编辑  收藏  举报