P2375 动物园 题解

题意简述:给定字符串,num[i]定义为该字符串前i个字符构成的前缀的最长不相交可匹配前缀后缀的个数,求(num[i]+1)的乘积。

分析:很容易想到暴力跳nxt的方法,nxt跳到前缀长度一半时开始计数,但很可惜,时间复杂度为O(L^2),直接T飞。然后发现可以在求nxt的同时处理出step[i],表示从i跳到0所需要的次数,这样,只需要跳nxt直到第一次长度小于一半即可,然而时间复杂度依然没变。继续优化,发现主要是暴力跳nxt到长度一半这个过程太慢了,怎么优化呢?考虑倍增跳nxt。这样,就能将时间复杂度降为O(LlogL)了。

代码:

#include<stdio.h>
#include<string.h>
#define ll long long
const int N=1e6+10;
const ll p=1e9+7;
int n;
int nxt[N],lg[N],num[N],step[N];
int jump[N][20+2];
char s[N];
void get_nxt() 
{
	nxt[1]=0; step[1]=0; int i=1,j=0;
	while (i<=n)
	  if ((j==0)||(s[i]==s[j]))
	    {
	       i++; j++;
	       nxt[i]=j; step[i]=step[j]+1;
		}
	  else
	    j=nxt[j];
}
void get_lg()
{
	for (int i=1;i<=N-5;i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i); 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值