zoukankan      html  css  js  c++  java
  • Manacher算法学习笔记

    @(学习笔记)[Manacher]

    问题概述

    给定一个串(str), 要求出其以每一位为对称中心的最长回文串的长度

    解决方法

    思路: 充分利用已有信息, 做到(O(n))复杂度.
    首先明确一下字符串(str)的一个子串的表示方式: (str[i ... j] (i le j))表示原串从第(i)位到第(j)位形成的子串; (str[j ... i] (i le j))反之.
    我们发现回文串有两种, 一种长度为奇数(如(ababa)), 另一种长度为偶数(如(abba)). 它们的对称中心是不一样的, 分别是一个字母和两个字母见的空隙. 为了避免分类讨论, 我们在每两个字母之间插入一个分隔符, 这样就只要考虑长度为奇数的回文串了. 我们令p[i]表示以第(i)位为对称中心的回文串向两边延伸的最大长度(包含对称中心, 例如串(a|b|b|a)(p[4] = 4)). 假设我们已经处理出(p[0 ... i - 1])的值, 我们记录下(p[j in [0, i - 1]] + j)的最大值mx, 和以(mx)为结尾的回文串的对称中心id. 对于当前一位(i), 不难发现, (str[i ... mx])(str[id cdot 2 - i ... id - p[id]])在位置上关于(id)对称, 因此它们不超出([id - p[id], id + [id]])的部分是相等的. 我们只需要在已有的这一部分的基础上继续往外扩张匹配, 然后再更新(mx)(id)即可.

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    
    const int LEN = 1 << 20;
    
    namespace Zeonfai
    {
    	inline char getChar()
    	{
    		char c;
    
    		for(c = getchar(); ~ c; c = getchar());
    
    		return c;
    	}
    }
    
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("manacher.in", "r", stdin);
    	freopen("manacher.out", "w", stdout);
    	#endif 
    	
    	using namespace Zeonfai;
    
    	static char str[LEN << 1];
    	int len = 0;
    	str[len ++] = '<', str[len ++] = '#';
    	char c;
    
    	while(~ (c = getchar()))
    		str[len ++] = c, str[len ++] = '#';
    
    	str[len ++] = '>';
    	int mx = 0, id = 0, ans = 0;
    	static int p[LEN << 1];
    
    	for(int i = 0; i < len; ++ i)
    	{
    		p[i] = mx > i ? std::min(mx - i, p[(id << 1) - i]) : 1;
    
    		for(; str[i - p[i]] == str[i + p[i]]; ++ p[i]);
    
    		if(p[i] + i > mx)
    			mx = p[i] + i, id = i;
    
    		ans = std::max(ans, p[i]);
    	}
    
    	printf("%d", ans - 1);
    }
    
  • 相关阅读:
    网页特殊符号HTML代码大全
    检测手机类型正则表达式
    blur和focus的运用
    腾讯对外分享组件接口文档
    js 类型检测
    iconfont的应用
    运算符优先级 (JavaScript)
    IOC(控制反转)和DI(依赖注入)
    Mybatis的运行原理
    通用Mapper
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/6691824.html
Copyright © 2011-2022 走看看