最长回文子串

采用hihoCoder测试系统,最长回文子串

实现中分别对比了string和char*,并且实现了经典的Manacher算法,不过发现Manacher算法并非最快的,可能因为涉及到字符串的生成问题吧。
注意LongestPalindrome2中的实现技巧。先寻找当前字符相同的字符,并且更新index,从而提高效率。
不过也遇到一个问题,在本地环境下,getchar+gets可以完成输入,并得到正确的结果,但是在hihoCoder的系统中,会提示wrong answer。经测试发现,问题出在getchar上。scanf(“%d\n”, &n) + gets这样也没有问题了。暂时不清楚原因。怀疑与编译器有关(G++)?
Manacher算法,理解了的话,还是很简单的,把奇偶转换为只考虑奇数的情况,然后利用之前计算出的结果以提升效率。想清楚如何利用就好了。

#include <iostream>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cstring> // strlen
using namespace std;

// 260ms    8MB
int LongestPalindrome1(const string &);
// 35ms 7MB
int LongestPalindrome2(const char *);
// Manacher
// 106ms    17MB
void format(char *, const char *);
int LongestPalindrome3(int *, const char *);
const int N = 1000002;
char s[N], str[2 * N];
int P[2 * N];
int main() {
    int n;
    cin >> n;
    /*string s;
    while (n--) {
    cin >> s;
    cout << LongestPalindrome1('$' + s) << endl;
    }*/

    getchar();
    //s[0] = '$';
    //while (n--) {
    //  //gets(s + 1);   // wrong answer????
    //  scanf("%s", s + 1);
    //  cout << LongestPalindrome2(s) << endl;
    //}


    while (n--) {
        scanf("%s", s);
        format(str, s);
        cout << LongestPalindrome3(P, str) << endl;
    }
    return 0;
}
int LongestPalindrome1(const string &str) {
    int size = str.size();
    int maxLen = 0;
    for (int i = 1, s, e, t; i < size; ++i) {
        s = i;
        e = i;
        while (e + 1 < size && str[e + 1] == str[i]) {
            ++e;
        }
        i = e;
        while (e + 1 < size && str[s - 1] == str[e + 1]) {
            --s;
            ++e;
        }
        if ((t = e - s + 1) > maxLen) {
            maxLen = t;
        }
    }
    return maxLen;
}
int LongestPalindrome2(const char *str) {
    int maxLen = 0;
    for (int i = 1, left, right; str[i]; ++i) {
        left = i;
        right = i;
        while (str[right + 1] == str[i]) {
            ++right;
        }
        i = right;
        while (str[left - 1] == str[right + 1]) {
            --left;
            ++right;
        }
        int t = right - left + 1;
        if (t > maxLen) {
            maxLen = t;
        }
    }
    return maxLen;
}

void format(char *str, const char *s) {
    str[0] = '$';
    str[1] = '#';
    int n = 2;
    for (int i = 0; s[i]; ++i) {
        str[n++] = s[i];
        str[n++] = '#';
    }
    str[n] = '\0';
}
int LongestPalindrome3(int *P, const char *str) {
    int ma = 0, re;
    for (int i = 1; str[i]; ++i) {
        if (ma > i) {
            P[i] = min(ma - i, P[2 * re - i]);
        }
        else {
            P[i] = 1;
        }
        while (str[i - P[i]] == str[i + P[i]]) {
            ++P[i];
        }
        if (P[i] + i > ma) {
            ma = P[i] + i;
            re = i;
        }
    }
    int ans = 0;
    for (int i = 0; i < strlen(str); ++i) {
        ans = max(ans, P[i] - 1);
    }
    return ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值