能當最小位置的值必定是一個最小後綴,而有用的最小後綴不超過\(\log n\)個c++
爲何不超過\(\log n\)個,看了一下zsy的博客。。spa
假如\(i = AAB\),\(j = AB\),\(B\)是\(A\)的一個嚴格前綴,\(|j| < |i| < 2|j|\)code
可是有\(k = B\),致使了若\(j\)比\(i\)優,則\(k\)會比\(j\)優,\(j\)比\(k\)優,則\(i\)會比\(j\)優,那麼\(j\)就沒用了get
而後取這\(\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(); }