P8617 [蓝桥杯 2014 国 AC] 重复模式 题解
题目描述不是很清晰,实际上
先说一下部分分做法,考虑二分,二分长度,利用 hash 和 map 来进行复杂度为
考虑使用 SAM 求出来所有子串的出现次数和长度,如果一个子串出现了
#include <bits/stdc++.h>
using namespace std;
#define N 500005
#define For(i, j, n) for(register int i = j ; i <= n ; ++i)
int ans, cnt, len, last;
int a[N], l[N], fa[N], go[N][26], siz[N];
string s;
inline void insert(int x){
int p = last, np = ++cnt;
last = np, siz[np] = 1, l[np] = l[p] + 1;
for( ; !go[p][x] && p ; p = fa[p]) go[p][x] = np;
if(!p) return fa[np] = 1, void();
int nq = go[p][x];
if(l[nq] == l[p] + 1) fa[np] = nq;
else{
int q = ++cnt;
fa[q] = fa[nq], fa[nq] = fa[np] = q;
l[q] = l[p] + 1;
memcpy(go[q], go[nq], sizeof(go[nq]));
for( ; go[p][x] == nq ; p = fa[p]) go[p][x] = q;
}
}
inline bool cmp(int x, int y){ return l[x] > l[y]; }
int main(){
cin >> s, cnt = last = 1;
for(auto i : s) insert(i - 'a');
For(i, 1, cnt) a[i] = i;
sort(a + 1, a + cnt + 1, cmp);
For(i, 1, cnt){
siz[fa[a[i]]] += siz[a[i]];
if(siz[a[i]] > 1) ans = max(ans, l[a[i]]);
}
printf("%d", ans);
return 0;
}