zoukankan      html  css  js  c++  java
  • 浅谈Manacher算法

    Manacher

    manacher是一种(O(n))求最长回文子串的算法,俗称马拉车(滑稽)

    直接步入正题

    首先可以知道的是:每一个回文串都有自己的对称中心,相应的也有自己的最大延伸长度(可以称之为“半径”)

    我们设(rad[i])表示以(i)为中心的回文子串的半径,那么只需要知道所有的(rad[i])就可以求出最长回文子串了

    (1)(n)枚举(i),求解(rad[i])

    设当前已经求到了(rad[k]),设前(k-1)个数中(rad[i]+i)(即右端点)最大的数为(mid),令(r=mid+rad[mid])

    那么可以证明一个点(i)关于(mid)的对称点是(2 imes mid-i)(两点距离公式)

    opt1:如果(kleq r)

    1574412665820

    方便起见,令(j=2 imes mid-k)

    1.若(j-rad[j]>mid-rad[mid]),即以(j)点为中心的最长回文子串的左端点在以(mid)为中心的最长回文子串的左端点右边,则(rad[i])可以直接由(rad[j])转移过来(因为(2 imes mid-r)~(mid)(mid)~(r)是对称的,所以(k)的半径和(j)的半径是一样的),即(rad[i]=rad[j])

    2.若(j-rad[j]leq mid-rad[mid]),则(rad[k])至少是(r-k)。接下来再暴力延伸,顺便更新(mid)(r)

    opt2:如果(k>r)

    直接暴力延伸,顺便更新(mid)(r)

    可以发现每次暴力延伸的时候,暴力延伸多少,(r)也会变化多少,且(r)是递增的且不超过(n)的数

    关于复杂度:

    由于每一个字符最多只会被遍历一次,所以复杂度是(O(n))

    实现细节:

    1.由于长度为偶数的回文串对称中心并不能实际找到,所以在两个字符之间插入#。这样不会影响答案,并且可以解决这个问题

    2.对于不同情况的相似之处可以合并到一起来降低码量,如op1.1的直接转移和opt1.2的转移等

    3.不要忘了更新(mid)(r)

    4.注意下标

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    char cString[22000005];
    int iRad[22000005];
    int iLen,iAns;
    
    void read()
    {
    	char c = getchar();
    	cString[0] = '|', cString[++iLen] = '#';
    	while(c < 'a' || c > 'z') c = getchar();
    	while(c >= 'a'&& c <= 'z') cString[++iLen] = c, cString[++iLen] = '#', c = getchar();
    }
    
    int main()
    {
    	read();//读入 
    	for(int i = 1, mid = 0, r = 0; i <= iLen; i++)
    	{
    		if(i <= r) iRad[i] = min(iRad[mid * 2 - i], r - i + 1);//opt1
    		while(cString[i - iRad[i]] == cString[i + iRad[i]]) ++iRad[i];//opt1.2,opt2 尝试暴力延伸 
    		if(i + iRad[i] > r) r = i + iRad[i] - 1, mid = i;//更新mid和r 
    		if(iRad[i] > iAns) iAns = iRad[i];//更新答案 
    	}
    	printf("%d", iAns-1);
    }
    
  • 相关阅读:
    父子进程 signal 出现 Interrupted system call 问题
    一个测试文章
    《淘宝客户端 for Android》项目实战 html webkit android css3
    Django 中的 ForeignKey ContentType GenericForeignKey 对应的数据库结构
    coreseek 出现段错误和Unigram dictionary load Error 新情况(Gentoo)
    一个 PAM dbus 例子
    漫画统计学 T分数
    解决 paramiko 安装问题 Unable to find vcvarsall.bat
    20141202
    js
  • 原文地址:https://www.cnblogs.com/lcezych/p/11912746.html
Copyright © 2011-2022 走看看