zoukankan      html  css  js  c++  java
  • hihoCoder#1032 最长回文子串

    原题地址

    这道题巧妙地利用了先前回文串的信息来减少后面的回文串计算量。

    比如下面的字符串(圆圈代表字符)假设已经知道了某个字符的回文串情况(曲线连接的两个圆圈代表两个相同字符)

    思考:这能给后面的回文串计算带来什么帮助呢?

    一个巴掌拍不响,看看已知两个回文串有什么效果:

    是不是有点意思了?为了更加直观,我们给曲线和点染色:

    还没明白在说什么?没关系,让我们把字母标上:

    这下非常明显了吧,已知中心点在i和中心点在j的两个回文串,现在要求中心点在k的回文串,我们很容易就知道这个回文串的长度至少是5(3个蓝色点+2个橙色点)。

    注意,这里求得的只是一个下界,目的是减少后续判定回文串的工作量。

    令f[i]表示以i为中心点的回文串的长度,那么则有f[k] >= 5

    原则上讲,k之前的所有已知回文串都可以用于计算这个下界,但毕竟我们就是计算一个下界,没必要非常精确。所以只是基于一个直观的想法去决定选择哪个点作为计算依据。即选择令 i + f[i] / 2 最大的那个i就行了。为什么是这个数呢?

    假设有两个候选,i和i',他们对应的回文串情况如下图所示。

    那我们应该用i还是用i'呢?我想,正常人应该都会选择用i而不是i'吧。。

    而上面那个式子(i + f[i] / 2)指的恰好就是回文串的右边界,也就是说,用这个i计算“应该”结果不赖。

    好了,i确定了,j怎么办呢?因为我们知道一个巴掌拍不响啊。其实选择j非常简单,只需要把k沿着i对称一下就行了:

    我们有f[k]' = f[j]。

    记住,f[k]'只是f[k]的一个下界,所以要想求得f[k]真正是多少,还是需要继续判断回文串,但是下界范围内的就不需要了,这就减少了判断回文串的工作量。

    知道原理以后,代码就很好写了。

    一开始我总是TLE,后来发现原来是用了C++的string的拼接,当string很长的时候,字符串的拼接是非常耗时的,所以要用字符数组,不能用字符串!

  • 相关阅读:
    C#校验算法列举
    SuperSocket1.6电子书离线版
    C#检测系统是否激活[转自StackOverFlow]
    WSMBT Modbus & WSMBS Modbus 控件及注册机
    AU3获取系统激活信息
    JavaScript跨浏览器事件处理
    OAuth2的学习小结
    R学习日记——分解时间序列(季节性数据)
    R学习日记——分解时间序列(非季节性数据)
    Java内存分配原理
  • 原文地址:https://www.cnblogs.com/boring09/p/4346085.html
Copyright © 2011-2022 走看看