[POI2006] OKR-Periods of Words——最大周期长度(扩展最小周期长度)

2023-11-09 20:15

本文主要是介绍[POI2006] OKR-Periods of Words——最大周期长度(扩展最小周期长度),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

[POI2006] OKR-Periods of Words——最大周期长度(扩展最小周期长度)

[原题链接](P3435 [POI2006] OKR-Periods of Words - 洛谷 | 计算机科学教育新生态 (luogu.com.cn))


字符串的周期

讲这道题之前,我们先聊一聊字符串的周期。我们要明确周期border两个概念

周期

对字符串 s s s 0 < p ≤ ∣ s ∣ 0<p\leq \left|s \right| 0<ps,若 s [ i ] = s [ i + p ] s[i]=s[i+p] s[i]=s[i+p]对所有 i ∈ [ 0 , ≤ ∣ s ∣ − p − 1 ] i \in [0,\leq \left|s \right| -p-1] i[0,sp1] 成立,则称 p p p s s s的周期

border

对字符串 s s s 0 < p < ∣ s ∣ 0<p< \left|s \right| 0<p<s,若s长度为r的前缀和长度为r的后缀相等,就称s长度为r的前缀是s的border

由s由长度为r的border可以推导出 ≤ ∣ s ∣ − r \leq \left|s \right|-r sr是s的周期

根据kmp的next数组,可以得到s(下标从0开始)的所有border长度,next[n-1],next[next[n-1]-1],…

显然s的最小周期 n − n e x t [ n − 1 ] n-next[n-1] nnext[n1]

思路

现在我们回到该题:

该题就是让我们求字符串 s 1 s_1 s1的最小周期

代码

代码如下

#include <bits/stdc++.h>using namespace std;const int N = 1e6 + 10;char c[N];
int ne[N];int main() {ios::sync_with_stdio(false);cin.tie(nullptr);int n;// 字符串下标从1开始cin >> n >> c + 1;// 获取next数组for (int i = 2, j = 0; i <= n; i ++) {while (j && c[i] != c[j + 1])j = ne[j];if (c[i] == c[j + 1]) {j ++;ne[i] = j;}}cout << n - ne[n];return 0;
}

扩展:最大周期长度

让每一个next数组的值都是最短前缀

核心代码

int j = n;
// 转换为最短前缀
while (ne[j]) j = ne[j];
// 记忆化存储
if (ne[i])  ne[i] = j;
// 最大周期长度
len = n - j;

例题

[[POI2006] OKR-Periods of Words](P3435 [POI2006] OKR-Periods of Words - 洛谷 | 计算机科学教育新生态 (luogu.com.cn))

分析

求每个子串的最大周期长度

样例分析

bab 2

baba 2

babab 4

bababa 4

bababab 6

babababa 6

参考代码

#include <iostream>using namespace std;const int N = 1e6 + 10;
typedef long long LL;char s[N];
LL ne[N];int main() {ios::sync_with_stdio(0);cin.tie(0);int n;cin >> n >> s + 1;for (int i = 2, j = 0; i <= n; i ++) {while (j && s[i] != s[j + 1])j = ne[j];if (s[i] == s[j+1])j ++;ne[i] = j;}LL ans = 0;for (int i = 2; i <= n; i ++) {int j = i;while (ne[j]) {j = ne[j];}if (ne[i])  ne[i] = j;ans += i-j;}cout << ans << endl;return 0;
}

这篇关于[POI2006] OKR-Periods of Words——最大周期长度(扩展最小周期长度)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/378259

相关文章

如何提高Redis服务器的最大打开文件数限制

《如何提高Redis服务器的最大打开文件数限制》文章讨论了如何提高Redis服务器的最大打开文件数限制,以支持高并发服务,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录如何提高Redis服务器的最大打开文件数限制问题诊断解决步骤1. 修改系统级别的限制2. 为Redis进程特别设置限制

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

poj 1287 Networking(prim or kruscal最小生成树)

题意给你点与点间距离,求最小生成树。 注意点是,两点之间可能有不同的路,输入的时候选择最小的,和之前有道最短路WA的题目类似。 prim代码: #include<stdio.h>const int MaxN = 51;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int P;int prim(){bool vis[MaxN];

poj 2349 Arctic Network uva 10369(prim or kruscal最小生成树)

题目很麻烦,因为不熟悉最小生成树的算法调试了好久。 感觉网上的题目解释都没说得很清楚,不适合新手。自己写一个。 题意:给你点的坐标,然后两点间可以有两种方式来通信:第一种是卫星通信,第二种是无线电通信。 卫星通信:任何两个有卫星频道的点间都可以直接建立连接,与点间的距离无关; 无线电通信:两个点之间的距离不能超过D,无线电收发器的功率越大,D越大,越昂贵。 计算无线电收发器D

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

poj 1734 (floyd求最小环并打印路径)

题意: 求图中的一个最小环,并打印路径。 解析: ans 保存最小环长度。 一直wa,最后终于找到原因,inf开太大爆掉了。。。 虽然0x3f3f3f3f用memset好用,但是还是有局限性。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#incl

hdu 1102 uva 10397(最小生成树prim)

hdu 1102: 题意: 给一个邻接矩阵,给一些村庄间已经修的路,问最小生成树。 解析: 把已经修的路的权值改为0,套个prim()。 注意prim 最外层循坏为n-1。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstri

poj 3723 kruscal,反边取最大生成树。

题意: 需要征募女兵N人,男兵M人。 每征募一个人需要花费10000美元,但是如果已经招募的人中有一些关系亲密的人,那么可以少花一些钱。 给出若干的男女之间的1~9999之间的亲密关系度,征募某个人的费用是10000 - (已经征募的人中和自己的亲密度的最大值)。 要求通过适当的招募顺序使得征募所有人的费用最小。 解析: 先设想无向图,在征募某个人a时,如果使用了a和b之间的关系

poj 3258 二分最小值最大

题意: 有一些石头排成一条线,第一个和最后一个不能去掉。 其余的共可以去掉m块,要使去掉后石头间距的最小值最大。 解析: 二分石头,最小值最大。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <c