求最长回文序列(pat 1040. Longest Symmetric String)

求最长回文子串问题—Manacher算法(O(n))

1.对原串进行转换
求回文串时奇偶串的算法会有差异,在这里做一个简单的处理,将奇回文串和偶回文串统一考虑,在每个字符间插入一个分隔符,串的首尾也要加,一般用“#”或“$”等。
原串:papapa
新串:#p#a#p#a#p#a#
这样一来,原来奇回文串还是奇数长度,偶数长度的回文串变成以“#”为中心的奇数回文串了。
2.len数组的性质
len[i]表示以字符T[i]为中心的最长回文半径
新串:# p # a # p # a # p # a #
len: 1 2 1 4 1 6 1 6 1 4 1 2 1
len数组有一个性质:len[i]-1为该回文串在原字符串中的位置
证明:
以T[i]为中心的最长回文字符串,其长度为:L=2*len[i]-1
以T[i]为中心的回文串一定是以“#”开头和结尾的,例如#p#a#p#,所以L减去最前面的#字符就是原串长度的二倍,即原串长为(L-1)/2,也即len[i]-1
3.len数组计算
从左往右依次计算Len[i],当计算Len[i]时,len[j]已经计算完毕(0<=j

// pata1040.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include"iostream"
#include"string"
#include"algorithm"
using namespace std;

const int N = 2005;

int main(){
    string str;
    getline(cin,str);  //使用getline输入可以接收空格
    int strlen = str.size();

    //添加“#”字符生成新串
    string strtmp = "#";
    for (int i = 0; i < strlen; i++)
        strtmp += str.substr(i, 1) + "#";

    //mx为之前计算的最长回文串的右端点的最大值,id为取得这个最大值的位置的id
    int id = 1, mx = 0;
    int len[N];


    for (int i = 0; i < strtmp.size(); i++){
        if (mx>i)
            len[i] = min(len[2 * id - i], mx - i);
        else
            len[i] = 1;
        while (i >= len[i] && strtmp.substr(i + len[i], 1) == strtmp.substr(i - len[i], 1))
            len[i]++;
        if (i + len[i] > mx){
            mx = i + len[i];
            id = i;
        }
    }
    int res = 1;
    for (int i = 1; i < strtmp.size(); i++){
        res = max(res, len[i]);
    }
    cout << res - 1 << endl;
    return 0;
}

https://github.com/tewzh/pat/blob/master/.gitignore/a1040%20Longest%20Symmetric%20String

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值