好久没有刷题了,虽然参加过ACM,但是始终没有融会贯通,没有学个彻底。我干啥都是半吊子,一瓶子不满半瓶子晃荡。
就连简单的Manacher算法我也没有刷过,常常为岁月蹉跎而感到后悔。

问题描述

给定一个字符串s,求最长回文子串。
回文子串的回文指的是abccba这种从前往后读和从后往前读一样。
子串必须连续(比如从i到j,s[i:j]),不是最长子序列(最长回文子序列怎么求?),子序列是可以不连续的。

算法大意

ans[i]表示以字符i为中心的最长回文子串的长度
now表示now+ans[now]取得最大值的那个下标
对于当前字符i,如果i处在以now为中心的回文子串里,那么ans[i]的求法可以参考i关于now的对称点的回文子串长度,也就是ans[now-(i-now)].
例如:1j34now67i9,假设ans[j]=1,那么ans[i]也等于1,因为i和j都处在以now为中心的回文子串里面,它们是对称的。

上面所述即为算法关键,其余情形很容易自己想到。
但是Manacher算法用到了两个技巧

加#号,统一处理

ans[i]中记录的是以i为中心的最长回文子串,如果不作处理,这样只能够检测出长度为奇数的回文子串的最大长度。所以有一个巧妙的预处理。
给定字符串abcc,扩充成#a#b#c#c#。
#a#b#a# 长度为3,以字符为中心的情况
#a#a#a#a# 长度为4,以#为中心的情况
这样奇数偶数统一化处理。

首部加上一个怪异字符$,减少条件判断

如果在for循环中检测两个条件,那是很费事的,效率低。
如何判断一个条件有很多次无效的判断?就看这个条件发挥作用,影响程序分支的次数和进行条件求值的次数。
边界条件判断影响分支的次数很少,但却每次都要进行判断。
通过加上一个终止字符,就能够避免边界条件判断。
在Manacher算法中,要求回文子串同时要防止下标越界。所以直接在开头插入一个\$字符,这样肯定因为失配而终止。

复杂度分析

Manacher算法为线性复杂度,因为从前往后有一个指针一直是单方向运动,没有回溯。
对于数组中的多个指针,如果都是单向运动,尽管它们运动的顺序和步长不同,那也一定是线性复杂度。

代码

#include<stdio.h>
#include<iostream>
using namespace std;
const int N = 110009;
char s[N];
char a[N * 2];
int ans[N * 2];
int now;
int main(){
    freopen("in.txt", "r", stdin);
    while (scanf("%s", s) != -1){
        if (s[0] == 0)continue;
        //#号法预处理
        int j = 0;
        a[j++] = '$';//这样就能少判断一点,不用考虑边界问题了
        for (int i = 0; s[i]; i++){
            a[j++] = '#';
            a[j++] = s[i];
        }
        a[j++] = '#';
        //开始算法主体部分
        now = 1;
        ans[0] = ans[1] = 0;
        for (int i = 2; i < j; i++){
            if (now + ans[now] < i){//如果当前字符不在阴影里,只能自力更生
                int k = i;
                while (a[k] == a[i - (k - i)]) k++;
                ans[i] = k - i - 1;
                now = i;
            }
            else{
                int right = now - (i - now);
                if (right - ans[right]>now - ans[now]){
                    ans[i] = ans[right];
                }
                else{
                    int k = now + ans[now];
                    while (a[k] == a[i - (k - i)])k++;
                    ans[i] = k - i - 1;
                    now = i;
                }
            }
        }
        //寻找答案,这部分可以直接放在求ans的过程中
        int ma = 0;
        for (int i = 1; i < j; i++){
            if (ma < ans[i])ma = ans[i];
        }
        printf("%d\n", ma);
    }
    return 0;
}

最长回文子序列

动态规划:复杂度都是O(n^2)
方法一:
a[i,j]表示s[i,j]之间最长回文子序列。则a[i,j]可以来自a[i+1,j-1],a[i-1,j],a[i,j-1].
方法二:
将s和s反过来得到的字符串求最长公共子序列

HDU3068 回文串 Manacher算法的更多相关文章

  1. 最长回文---hdu3068 (回文串 manacher 算法模板)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3068 题意很清楚:就是求一个串s的子串中最长回文串的长度:这类题用到了manacher算法 #incl ...

  2. luoguP4555 [国家集训队]最长双回文串 manacher算法

    不算很难的一道题吧.... 很容易想到枚举断点,之后需要处理出以$i$为开头的最长回文串的长度和以$i$为结尾的最长回文串的长度 分别记为$L[i]$和$R[i]$ 由于求$R[i]$相当于把$L[i ...

  3. bzoj 2565: 最长双回文串 manacher算法

    2565: 最长双回文串 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem. ...

  4. 37:密码截取(回文串manacher算法)

    题目描述:Catcher是MCA国的情报员,他工作时发现敌国会用一些对称的密码进行通信,比如像这些ABBA,ABA,A,123321,但是他们有时会在开始或结束时加入一些无关的字符以防止别国破解.比如 ...

  5. 【BZOJ2565】最长双回文串 (Manacher算法)

    题目: BZOJ2565 分析: 首先看到回文串,肯定能想到Manacher算法.下文中字符串\(s\)是输入的字符串\(str\)在Manacher算法中添加了字符'#'后的字符串 (构造方式如下) ...

  6. UESTC-1975弗吉桑(回文串,manacher算法)

    弗吉桑 Time Limit: 3000 MS     Memory Limit: 64 MB Submit Status 弗吉桑是一座横跨清水河大草原的活火山,位于子科技大学主楼东北方约 80km ...

  7. 回文串--Manacher算法(模板)

    用途:在O(n)时间内,求出以每一个点为中心的回文串长度. 首先,有一个非常巧妙的转化.由于回文串长度有可能为奇数也有可能为偶数,说明回文中心不一定在一个字符上.所以要将字符串做如下处理:在每两个字母 ...

  8. Palindrome(最长回文串manacher算法)O(n)

     Palindrome Time Limit:15000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit ...

  9. 九度OJ 1528 最长回文子串 -- Manacher算法

    题目地址:http://ac.jobdu.com/problem.php?pid=1528 题目描述: 回文串就是一个正读和反读都一样的字符串,比如"level"或者"n ...

随机推荐

  1. 配置Chrome支持本地(file协议)的AJAX请求

    什么问题 WEB开发过程中,很多时候我们都是写一些简单的Demo,并不是开发一个完整项目,此时我们常见的操作是: 新建文件夹 新建需要的文件 在Sublime(或其他编辑器)中完成DEMO的编码 双击 ...

  2. Python 正则表达式入门(初级篇)

    Python 正则表达式入门(初级篇) 本文主要为没有使用正则表达式经验的新手入门所写. 转载请写明出处 引子 首先说 正则表达式是什么? 正则表达式,又称正规表示式.正规表示法.正规表达式.规则表达 ...

  3. 4D卓越团队-两天培训总结

    上周末参加了公司组织的领导力培训课程-4D卓越团队(创业型团队领导力训练项目),感觉有一些用,在这里分享一下. 课前游戏 培训老师先带我们做了一个游戏:每一个人,在同时参加培训的人中找到另外的 6 个 ...

  4. WinServer2008R2 + IIS 7.5 + .NET4.0 经典模式 运行WebAPI程序报404错误的解决方案

    在Windows Server 2008 R2系统下,IIS 7.5 + .NET Framework 4.0的运行环境,以经典模式(Classic Mode)部署一个用.NET 4.0编译的 Web ...

  5. 使用命令 gradle uploadArchives 的异常: Unable to initialize POM pom-default.xml: Failed to validate POM for project

    在使用:gradle uploadArchives 命令对项目进行上传maven时,常常遇到如下报错: 这时候要仔细的检查一下build.gradle文件中的dependencies内容,很多时候是由 ...

  6. mysql技术点1.-----------查询当天的所有数据

    select xs.* from xn_supervision xs where  xs.task_type="+taskType+"  and  xs.create_time&g ...

  7. 如何利用FineBI做财务分析

    很多企业随着业务规模的增长,传统的财务分析方式采用手工摘取数据的方式,难以快速地对企财务经营状况作出及时分析和预测.现在业务人员通过使用自助式BI工具做财务分析已经成为流行,每个人都希望自己做报表,快 ...

  8. iOS - GitHub干货分享(APP引导页的高度集成 - DHGuidePageHUD - ①)

    好长时间没更新博客, 是时候来一波干货分享了;APP引导页话不多说每一个APP都会用到,分量不重但是不可缺少,不论是APP的首次安装还是版本的更新,首先展现给用户眼前的也就只有它了吧,当然这里讲的不是 ...

  9. iOS - UITableView中Cell重用机制导致Cell内容出错的解决办法

    "UITableView" iOS开发中重量级的控件之一;在日常开发中我们大多数会选择自定Cell来满足自己开发中的需求, 但是有些时候Cell也是可以不自定义的(比如某一个简单的 ...

  10. MBProgressHUD 显示后,为何不能点击屏幕其他地方

    解决办法: hud.userInteractionEnabled= NO;  就是这么简单粗暴!这个问题 我一定要发到首页候选区! /********************************* ...