CF1286E

显然只需要考虑每次加入一个新点的答案。
把加点之后不再是 border 的 border 删掉,把仍然是border的用 w[i] 更新一下答案(取个min)。
每次最多加入一个border,每个border最多会被删除一次。所以是O(n)的。
而每次用map暴力更新答案的话,均摊O(logn)


以上内容默认看过题解。
时间复杂度瓶颈在于如何找到不合法的。
多数题解都说:“用kmp的失配指针构建一棵树” 或 “画出kmp的fail树”。看不懂。

附一张fail树的配图:
image
我们定义一个位置 i 的颜色为 s[nxt[i]+1]
首先插入 i 之前的 border 都是针对 i1 合法的 border,所以都是在 i1 的 fail 树上的。
考虑暴力 : 从 i1开始暴力跳nxt,看 fail 树上每个位置是否合法(颜色是否等于s[i])。
优化一下,一共有26种颜色(26个字母),而我们只留下一种(s[i]),维护一个数组lst[i][j],表示在 i 所处的 fail 树上,在 i 之前第一个颜色为 j 的位置,然后.......就硬跳。

upd:如果暴力跳是可能被卡成 O(n2) 的,而维护了颜色后,每次跳到的border都是要删除的,而每个border只会被删除一次,所以均摊 O(1)

点击查看代码
for(int j = 0 ; j < 26 ; j++)lst[i][j] = lst[nxt[i]][j];
lst[i][s[nxt[i]+1]-'a'] = nxt[i];
for(int j = 0 ; j < 26 ; j++)
{
if(j + 'a' == s[i])continue;
for(ll k = lst[i-1][j] ; k ; k = lst[k][j])
{
ll val = query(1,1,n,i-k,i-1);
mp[val]--;
ans -= val;
}
}
posted @   5_Lei  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示