# 【做题】ECFinal2018 J - Philosophical … Balance——dp

$\min_{i=1}^n \left( \sum_{j=1}^n k_j {\rm {lcp}} (s[i:],s[j:]) \right)$
$n \leq 2 \times 10^5$

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
#define fir first
#define sec second
#define rep(i,a,b) for (int i = (a) ; i <= (b) ; ++ i)
#define rrp(i,a,b) for (int i = (a) ; i >= (b) ; -- i)
#define gc() getchar()
template <typename tp>
inline void read(tp& x) {
x = 0; char tmp; bool key = 0;
for (tmp = gc() ; !isdigit(tmp) ; tmp = gc())
key = (tmp == '-');
for ( ; isdigit(tmp) ; tmp = gc())
x = (x << 3) + (x << 1) + (tmp ^ '0');
if (key) x = -x;
}

const int N = 200010;
int ch[N << 1][26], fa[N << 1], len[N << 1], cnt = 1, las = 1;
bool tag[N << 1];
void append(char c) {
int np = ++ cnt, p = las;
tag[np] = 1;
las = np;
len[np] = len[p] + 1;
fa[np] = 1;
while (p && !ch[p][c - 'a'])
ch[p][c - 'a'] = np, p = fa[p];
if (!p) return;
int q = ch[p][c - 'a'];
if (len[q] == len[p] + 1)
fa[np] = q;
else {
int nq = ++ cnt;
len[nq] = len[p] + 1;
tag[nq] = 0;
fa[nq] = fa[q];
rep (i, 0, 25) ch[nq][i] = ch[q][i];
fa[q] = nq;
fa[np] = nq;
while (p && ch[p][c - 'a'] == q)
ch[p][c - 'a'] = nq, p = fa[p];
}
}
struct edge {
int la,b;
} con[N << 1];
int tot,fir[N << 1];
void add(int from,int to) {
con[++tot] = (edge) {fir[from], to};
fir[from] = tot;
}
char str[N];
int n;
db dp[N << 1];
void dfs(int pos) {
if (tag[pos]) {
dp[pos] = len[pos];
return;
}
db tmp = 0;
for (int i = fir[pos] ; i ; i = con[i].la)
dfs(con[i].b), tmp += 1.0 / (dp[con[i].b] - len[pos]);
dp[pos] = 1.0 / tmp + len[pos];
}
void solve() {
scanf("%s", str + 1);
n = strlen(str + 1);
tot = 0;
las = cnt = 1;
memset(fir,0,sizeof(int) * (2 * (n + 5)));
memset(ch,0,sizeof(int) * (26 * 2 * (n + 5)));
rrp (i, n, 1) append(str[i]);
rep (i, 2, cnt) add(fa[i], i);
dfs(1);
printf("%.10lf\n", dp[1]);
}
int main() {
int T;
read(T);
while (T --)
solve();
return 0;
}

posted @ 2019-03-06 10:27 莫名其妙的aaa 阅读(...) 评论(...) 编辑 收藏