zoukankan      html  css  js  c++  java
  • manacher算法

    manacher算法是在O(n)的复杂度内求回文串长度的算法。

    算法过程如下。

    先在所有字符之间加上一种没有意义的字符。

    比如“#”,“|”等。来去除偶数回文和奇数回文的区别。

    再在第0位加上“~”,这样就可以保证不会出范围。

    其中rb表示当前mid的回文串右边界。

    枚举中间点 i 如果 i 在右边界之前。

    p[i],也就是i时的回文半径。 j 为 i 关于mid的对称点。

    关于mid的更新在下面再说。

    p[ i ] = min( p[ j ] , rb-i );

    这句话尝试用j的回文长度来求i的回文长度。

    因为关于mid对称,所以p[i]可以等于p[j]。

    如果i在右边界之后,则p[i]=1;

    那么就可以继续向后查。

    while(da[i-p[i]]==da[i+p[i]])

      p[i]++;

    将半径扩大。

    这时候如果p[i]+i大于rb,也就是现在的范围超出了原来的范围。

    那么可以更新rb=p[i]+i;  那么 mid=i; 

    总体算法结束。

    那么最后的答案,最长回文长度就是最长半径-1。(为什么减一?规律哈哈哈哈)

    模板:https://www.luogu.org/problemnew/show/P3805

    代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=11000001;
    char da[maxn<<1];
    int p[maxn<<1],cnt=1;
    int rb,maxx,mid;
    int main()
    {
        char c=getchar();
        da[0]='~';
        da[1]='#';
        while(c>'z'||c<'a')
            c=getchar();
        while(c<='z'&&c>='a'){
            da[++cnt]=c;
            da[++cnt]='#';
            c=getchar();
        }
        for(int i=1;i<=cnt;i++){
            if(i<rb)
                p[i]=min(p[(mid<<1)-i],rb-i);
            else p[i]=1;
            while(da[i-p[i]]==da[i+p[i]])
                p[i]++;
            if(p[i]+i>rb)
                rb=p[i]+i,mid=i;
            maxx=max(p[i],maxx);
        }
        printf("%d
    ",maxx-1);
        // while(1);
        // system("pasue");
        return 0;
    }
  • 相关阅读:
    Win32中精确计时器(微秒级)
    一个封装文件操作和目录操作的类
    CString
    两个经典的RGB与YUV转换函数
    C++文件流
    HSI、HSV、RGB、CMY、CMYK、HSL、HSB、Ycc、XYZ、Lab、YUV颜色模型
    MPEG4与H264区别,编码及应用
    C file文件基本知识
    RGB ,YUV, YCbCr的定义
    在android平台上测试C/C++程序及库
  • 原文地址:https://www.cnblogs.com/ChrisKKK/p/11166596.html
Copyright © 2011-2022 走看看