【bzoj1511】[POI2006]OKR-Periods of Words KMP-next数组

原文地址:http://www.cnblogs.com/GXZlegend/p/6827027.html



题目描述

一个串是有限个小写字符的序列,特别的,一个空序列也可以是一个串. 一个串P是串A的前缀, 当且仅当存在串B, 使得 A = PB. 如果 P A 并且 P 不是一个空串,那么我们说 P 是A的一个proper前缀. 定义Q 是A的周期, 当且仅当Q是A的一个proper 前缀并且A是QQ的前缀(不一定要是proper前缀). 比如串 abab 和 ababab 都是串abababa的周期. 串A的最大周期就是它最长的一个周期或者是一个空串(当A没有周期的时候), 比如说, ababab的最大周期是abab. 串abc的最大周期是空串. 给出一个串,求出它所有前缀的最大周期长度之和.

输入

第一行一个整数 k ( 1 k 1 000 000) 表示串的长度. 接下来一行表示给出的串.

输出

输出一个整数表示它所有前缀的最大周期长度之和.

样例输入

8

babababa

样例输出

24



题目大意

定义A串为B串的循环串,当且仅当A是B的前缀(不包括B本身),且B为连续的A串拼接的字符串的前缀。给出一个字符串,求它的所有前缀(包括本身)的最长循环串的长度之和。

题解

KMP-next数组

最长循环串长度=总长度-最短相同前后缀长度

求最短相同前后缀长度,根据next数组的定义:最长相同前后缀长度,可以一直取next,直到不能取为止,得到最短相同前后缀长度。

这样极限时间复杂度是O(n^2)。

我们可以想到:每次求完1次next之后的部分已经在之前求过,可以储存下来,下一次直接用。时间复杂度O(n)。

#include <cstdio>
char str[1000010];
int next[1000010] , cnt[1000010];
int main()
{
	int n , i = 0 , j = -1;
	long long ans = 0;
	scanf("%d%s" , &n , str);
	next[0] = -1;
	while(i < n)
	{
		while(~j && str[j] != str[i]) j = next[j];
		i ++ , j ++ , next[i] = j;
	}
	for(i = 1 ; i <= n ; i ++ )
	{
		if(next[i] != 0) cnt[i] = cnt[next[i]];
		else cnt[i] = i;
		ans += i - cnt[i];
	}
	printf("%lld\n" , ans);
	return 0;
}
时间: 2024-10-13 10:23:41

【bzoj1511】[POI2006]OKR-Periods of Words KMP-next数组的相关文章

[POI2006][luogu3435] OKR-Periods of Words [kmp+next数组]

题面 传送门 思路 先把题面转成人话: 对于给定串的每个前缀i,求最长的,使这个字符串重复两边能覆盖原前缀i的前缀(就是前缀i的一个前缀),求所有的这些"前缀的前缀"的长度和 利用$next$的性质:前缀$i$的长度为$next[i]$的前缀和后缀是相等的 这说明:如果有i一个公共前后缀长度为j,那么这个前缀i就有一个周期为i-j 见下图 显然图中蓝色线段是黑色线段的一个周期 那么接下来的问题就容易了: 先求出$next$数组 对于每个前缀$i$,令$j=i$,然后在$j>0$的

HDOJ3336 Count the string 【KMP前缀数组】+【动态规划】

Count the string Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4212    Accepted Submission(s): 1962 Problem Description It is well known that AekdyCoin is good at string problems as well as n

字符串匹配KMP next数组的理解

#include<cstdio> #include<cstring> void getNext(int *Next,char* src){ int i,j; Next[0]=-1; i=0; j=-1; int N=strlen(src); while(i<N-1){ if(j==-1||src[i]==src[j]){ ++i; ++j; Next[i]=j; }else{ /* 理解难点:假设已经存在Next:假设是两个字符串在进行比较. 1. a)现在有两个字符串 sr

BZOJ1511: [POI2006]OKR-Periods of Words

1511: [POI2006]OKR-Periods of Words Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 174  Solved: 92[Submit][Status] Description 一 个串是有限个小写字符的序列,特别的,一个空序列也可以是一个串. 一个串P是串A的前缀, 当且仅当存在串B, 使得 A = PB. 如果 P A 并且 P 不是一个空串,那么我们说 P 是A的一个proper前缀. 定义Q 是A的周期, 当且仅当

Theme Section---hdu4763(kmp, Next数组的运用)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4763 题意就是求s串中满足EAEBE格式的E的最大长度:我们可以枚举前缀和后缀的所有匹配(k)看是否在s[k,len-k]中; 如果不在它中间那么就让k=Next[k],刚开始想的是k--:但是这样循环次数有点多(本题数据太水,k--也能过): 但是s[0,k-1]和s[len-k-1,len-1]不一定一样啊,如果是Next[k]的话那么前缀Next,即前缀的前缀和后缀肯定相等并且等于后缀的后缀(

POJ-3450 Corporate Identity (KMP+后缀数组)

Description Beside other services, ACM helps companies to clearly state their "corporate identity", which includes company logo but also other signs, like trademarks. One of such companies is Internet Building Masters (IBM), which has recently a

poj2406(kmp next数组)

大意:给出一个字符串 问它最多由多少相同的字串组成 如  abababab由4个ab组成 分析: kmp中的next数组求最小循环节的应用 例如 ababab  next[6] = 4; 即 ababab ababab 1~4位  与2~6位是相同的 那么前两位 就等于3.4位 3.4位就等于5.6位 …… 所以 如果 能整除  也就循环到最后了 如果不能整除 就最后余下的几位不在循环内 例如 1212121 1212121 最后剩余1不能等于循环节 代码: 1 #include <iostre

[hdu3336]kmp(后缀数组)

题意:求字符串s的所有前缀出现次数之和. http://www.cnblogs.com/jklongint/p/4446117.html 思路:用kmp做,简单且效率高.以前缀结尾的位置分类,令dp[i]为以结尾位置在i的前缀数量,那么dp[i] = cnt(j)(j~i是前缀),而由kmp的next函数的转移性质,可得如下递推方程:dp[i] = dp[next[i]] + 1,把这个递推式不断展开,也就是i = next[i]不断迭代,那么+1的个数就是dp[i] = cnt(j)(j~i是

HDU 5442——Favorite Donut——————【最大表示法+kmp | 后缀数组】

Favorite Donut Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1702    Accepted Submission(s): 430 Problem Description Lulu has a sweet tooth. Her favorite food is ring donut. Everyday she buy

POJ2406 Power Strings(KMP,后缀数组)

这题可以用后缀数组,KMP方法做 后缀数组做法开始想不出来,看的题解,方法是枚举串长len的约数k,看lcp(suffix(0), suffix(k))的长度是否为n- k ,若为真则len / k即为结果. 若lcp(suffix(0), suffix(k))的长度为n- k,则将串每k位分成一段,则第1段与第2段可匹配,又可推得第2段与第3段可匹配……一直递归下去,可知每k位都是相同的,画图可看出匹配过程类似于蛇形. 用倍增算法超时,用dc3算法2.5秒勉强过. #include<cstdi