【BZOJ2803】【Poi2012】Prefixuffix hash+推性质

链接:

#include <stdio.h>
int main()
{
    puts("转载请注明出处[vmurder]谢谢");
    puts("网址:blog.csdn.net/vmurder/article/details/45768837");
}

题解:

首先我们如果设原串为串[ 1,n ]

然后 fi 表示串[ i+1,n?i ]中最长的串长使得串[ i+1,i+fi ]==串[n?i?fi+1,n?i]

这时存在一个性质 fi?1<=fi+2

然后就可以线性递推啦!

证明:

现在让我们来反证一下这个性质:

下图有四种情况,f[i]为红色, f[i-1]为全图。

显然无论何时,f[i-1]对应图去掉两侧点,皆可以保证是一个f[i]。

所以fi?1<=fi+2

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1001000
#define mod 1000000009
#define base 1000000007
using namespace std;
int n,ans;
char s[N];
long long sum[N],hash[N],pw[N];
long long gethash(int l,int r)
{return (hash[r]+mod-hash[l-1]*pw[r-l+1]%mod)%mod;}
int main()
{
    freopen("test.in","r",stdin);

    int i,j,k;

    scanf("%d",&n);
    for(pw[0]=i=1;i<=n;i++)pw[i]=(long long)pw[i-1]*base%mod;
    scanf("%s",s+1);
    for(i=1;i<=n;i++)
    {
        hash[i]=(hash[i-1]*base%mod+s[i])%mod;
        sum[i]=sum[i-1]+s[i];
    }
    for(i=n>>1,j=0;~i;i--)
        if(sum[i]==sum[n]-sum[n-i])
            if(gethash(1,i)==gethash(n-i+1,n))
                for(j=min(n/2-i,j+2);j>=0;j--)
                    if(sum[i+j]-sum[i]==sum[n-i]-sum[n-i-j])
                        if(gethash(i+1,i+j)==gethash(n-i-j+1,n-i))
                            {ans=max(ans,i+j);break;}
    printf("%d\n",ans);
    return 0;
}
时间: 2024-11-08 13:55:50

【BZOJ2803】【Poi2012】Prefixuffix hash+推性质的相关文章

BZOJ 2803 Poi2012 Prefixuffix Hash

题目大意:给定一个字符串S,求一个最长的L(L*2<=n),使S长度为L的前缀和长度为L的后缀循环同构 一开始我的想法是枚举L,判断长度为L的前缀和长度为L的后缀的所有循环同构的哈希值之和是否相等 但是很快我发现这做法是扯淡- - 因为一个字符串所有循环同构的哈希值之和等于这个字符串所有字符ASCII码之和乘上(BASE^len+BASE^(len-1)+...+BASE^2+BASE+1) 然后我在想能不能考虑修改一下哈希函数呢? 比如给每个字符一个BASE,定义一个字符串的哈希值为以字符串开

【BZOJ2803】[Poi2012]Prefixuffix 结论题

[BZOJ2803][Poi2012]Prefixuffix Description 对于两个串S1.S2,如果能够将S1的一个后缀移动到开头后变成S2,就称S1和S2循环相同.例如串ababba和串abbaab是循环相同的.给出一个长度为n的串S,求满足下面条件的最大的L:1. L<=n/22. S的L前缀和S的L后缀是循环相同的. Input 第一行一个正整数n (n<=1,000,000).第二行n个小写英文字母,表示串S. Output 一个整数,表示最大的L. Sample Inpu

「AHOI2018 初中组」根式化简(分解质因数+推性质)

https://loj.ac/problem/2993 之前在哪里见过这个套路,但忘记了是在哪里了,在这里总结一下 暴力就是筛出\(n^{\frac{1}{3}}\)里的所有质数,然后用它们去分解. 这个有\(80p\). 事实上,我们可以只用\(n^{\frac{1}{4}}\)内的质数去分解,对于分解剩下的那个数\(x\). \(x\)的最小质因子\(>n^{\frac{1}{4}}\),所以它最多有\(4-1=3\)个质因子. 所以它要是想有一个\(3\)次以上的质因子,就只能是\(x^{

[luogu]P1066 2^k进制数[数学][递推][高精度]

[luogu]P1066 2^k进制数 题目描述 设r是个2^k 进制数,并满足以下条件: (1)r至少是个2位的2^k 进制数. (2)作为2^k 进制数,除最后一位外,r的每一位严格小于它右边相邻的那一位. (3)将r转换为2进制数q后,则q的总位数不超过w. 在这里,正整数k(1≤k≤9)和w(k<W≤30000)是事先给定的. 问:满足上述条件的不同的r共有多少个? 我们再从另一角度作些解释:设S是长度为w 的01字符串(即字符串S由w个“0”或“1”组成),S对应于上述条件(3)中的q

递推(一):递推法的基本思想

所谓递推,是指从已知的初始条件出发,依据某种递推关系,逐次推出所要求的各中间结果及最后结果.其中初始条件或是问题本身已经给定,或是通过对问题的分析与化简后确定. 利用递推算法求问题规模为n的解的基本思想是:当n=1时,解或为已知,或能非常方便地求得:通过采用递推法构造算法的递推性质,能从已求得的规模为1.2.….i−1的一系列解,构造出问题规模为i的解.这样,程序可从i=0或i=1出发,重复地由已知至i−1规模的解,通过递推,获得规模为i的解,直至获得规模为n的解. 可用递推算法求解的问题一般有

NOIP hzwer second - xgtao -

这一道题有两种做法: 1:构建矩阵,根据斐波拉契数列数列类比,得到矩阵过后根据fi直接解出t(因为fi是小于19960515的所以过程中不会去"%",所以可以直接除以系数,不 用逆元),再用矩阵算出fj |fn+1 |     |1 1|n   * |f1| |fn     |       |0 1|    * |f0| 2:找规律推性质: f0 =        1 f1 = 1t f2 = 1t + 1 f3 = 2t + 1 f4 = 3t + 2 f5 = 5t + 3 那么归

基本算法思想Java实现的详细代码

基本算法思想Java实现的详细代码 算法是一个程序的灵魂,一个好的算法往往可以化繁为简,高效的求解问题.在程序设计中算法是独立于语言的,无论使用哪一种语言都可以使用这些算法,本文笔者将以Java语言为例介绍一些常用的算法思想. 分类 穷举算法思想 递推算法思想 递归算法思想 分治算法思想 概率算法思想  穷举算法思想 穷举算法的基本思想 从所有可能情况中搜索正确答案 1. 对于一种可能情况,计算其结果. 2. 判断结果是否满足,如不能满足者执行第一步来搜索下一个可能的情况:如满足则表示选找到一个

【转】Java HashMap 源码解析(好文章)

- .fluid-width-video-wrapper { width: 100%; position: relative; padding: 0; } .fluid-width-video-wrapper iframe, .fluid-width-video-wrapper object, .fluid-width-video-wrapper embed { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } [

图像特征提取:图像的矩特征

1. 矩的概念 图像识别的一个核心问题是图像的特征提取,简单描述即为用一组简单的数据(图像描述量)来描述整个图像,这组数据越简单越有代表性越好.良好的特征不受光线.噪点.几何形变的干扰.图像识别发展几十年,不断有新的特征提出,而图像不变矩就是其中一个. 矩是概率与统计中的一个概念,是随机变量的一种数字特征.设X为随机变量,c为常数,k为正整数.则量E[(x−c)k]称为X关于c点的k阶矩. 比较重要的有两种情况: 1. c=0.这时ak=E(Xk)称为X的k阶原点矩 2. c=E(X).这时μk