[BZOJ 2803]Poi2012 Prefixuffix

25 篇文章 0 订阅

在说正解前先orz一下zy的神骗分算法——

枚举总长度——如果在1~i和n-i+1~n这一段字母acsii和相同则在做下一步判断惊讶

然后枚举判断啦。。。。居然只超时一个点(数据好和谐~~)!


回来说正解。

看到题解,好厉害的题目!

这题目有个好厉害的性质。我们用F[i]记下(i+1,n-i)的最大相同前缀后缀,那么F[i-1]<=F[i]+2

证明就用反证法,自己画了张拙图:



如果F[i-1]>F[i]+2,那么红色区域相同,也就是说F[i]可以变得更大。得证!

这样复杂度就变为O(n)了。

坑题还会卡hash,果断加上zy大法a掉生气

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
#define gethash(l,r) ((hash[(r)]-(long long)hash[(l)-1]*pw[(r)-(l)+1]%MaxQ+MaxQ)%MaxQ)
const int MaxP=(1e9)+7, MaxQ=(1e9)+9, Maxn=1000005;
int hash[Maxn], a[Maxn], pw[Maxn], ans, n, i, j;

int main(){
  freopen("pre.in","r",stdin);
  freopen("pre.out","w",stdout);
  scanf("%d\n",&n);
  for (i=1,pw[0]=1;i<=n;i++) pw[i]=(long long)pw[i-1]*MaxP%MaxQ;
  for (i=1;i<=n;i++){
    char ch=getchar(); a[i]=ch;
    hash[i]=((long long)hash[i-1]*MaxP%MaxQ+a[i])%MaxQ;
    a[i]+=a[i-1];
  }
  
  for (i=n/2,j=0;i>0;i--,j=min(n/2-i,j+2))
  if ( a[i]==a[n]-a[n-i] && gethash(1,i)==gethash(n-i+1,n) ){
  	for (;j>=0;j--)
  	if ( a[i+j]-a[i]==a[n-i]-a[n-i-j] )
	if ( gethash(i+1,i+j)==gethash(n-i-j+1,n-i) )
	 { ans=max(i+j,ans); break; }
  }
  printf("%d\n",ans);
  return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值