• 浅谈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);
    }
    
  • 相关阅读:
    HDU 5791 Two (DP)
    POJ 1088 滑雪 (DPor记忆化搜索)
    LightOJ 1011
    POJ 1787 Charlie's Change (多重背包 带结果组成)
    HDU 5550 Game Rooms (ccpc2015 K)(dp)
    HDU 5542 The Battle of Chibi (ccpc 南阳 C)(DP 树状数组 离散化)
    HDU 5543 Pick The Sticks (01背包)
    HDU 5546 Ancient Go (ccpc2015南阳G)
    NB-IoT的DRX、eDRX、PSM三个模式 (转载,描述的简单易懂)
    MQTT 嵌入式端通讯协议解析(转)
  • 原文地址:https://www.cnblogs.com/lcezych/p/11912746.html
Copyright © 2020-2023  润新知