hdu 5340 Manachers + 枚举

题意:给你一个字符串问能否拆分为三个回文字符串?能就输出yes,否则输出no。

知识补充:

最长回文子串算法(Manacher算法):

求解最长回文子串的线性时间复杂度算法,主要是通过中心扩展的方法极大地避免了重复计算。实现如下:

  • 为了避免对字符串奇偶数的讨论,先对字符串做预处理如下:
规则为在字符间和两边插入'#'字符,为了避免越界处理,最两边插入'^''$'字符。
原本字符串为:asd
预处理后为:^#a#s#d#$
  • 然后实现部分:设置两个变量:c 和 r,表示当前最长回文字符串的中心和边界。数组p[max],p[i]表示以i为中心的回文字符串的长度之后对字符串从左向右处理,有更长的回文字符串就更新c 和 r。这是有如下结论:对于以i为中心的字符串,如果i < r,那么就有:p[i] >= min(p[2 * c - i], r - i)。然后再进行扩展。即可
根据实现后得到的p数组和字符串的对应关系:
#a#s#s#d#
010121010

贴Manacher算法的模板:

Manacher算法:        
// 将S转换成T的预处理
// 比如,S = "abba", T = "^#a#b#b#a#$"
// ^和$符号用来表示开始和结束,并且避免边界检查。
string preProcess(string s)
{
    int n = s.length();
    if (n == 0) return "^$";
    string ret = "^";
    for (int i = 0; i < n; i++)
        ret += "#" + s.substr(i, 1);

    ret += "#$";
    return ret;
}

string longestPalindrome(string s)
{
    string T = preProcess(s);
    int n = T.length();
    int* P = new int[n];
    int C = 0, R = 0;
    for (int i = 1; i < n - 1; i++) {
        int i_mirror = 2 * C - i; // 等于i' = C - (i-C)

    P[i] = (R > i) ? min(R-i, P[i_mirror]) : 0;

    // 尝试扩展中心为i的回文
    while (T[i + 1 + P[i]] == T[i - 1 - P[i]])
        P[i]++;

    // 如果中心为i的回文超越了R,根据已扩展的回文来调整中心
    if (i + P[i] > R) {
        C = i;
        R = i + P[i];
        }
    }

    // 找出P中的最大值
    int maxLen = 0;
    int centerIndex = 0;
    for (int i = 1; i < n-1; i++) {
        if (P[i] > maxLen) {
            maxLen = P[i];
            centerIndex = i;
        }
    }
    delete[] P;

    //返回最大回文子串
    return s.substr((centerIndex - 1 - maxLen)/2, maxLen);
}

###这道题的思路:

  • 先用Manacher算法处理字符串,把以左端点为起点的回文子串的右端点加入到a数组中,把以右端点为终点的回文子串的左端点加入到b数组中(这里充分利用了Manacher算法处理之后得到的p数组,根据p[i]可以变换出,以i为中心的回文字符串在原串中的起点和终点)。然后枚举左边是a[i]结尾的字符串,和右边是b[j]开始的字符串,再由p数组判断他们中间的那个字符串是否是回文串即可。
  • 可以说这个题是Manacher算法的变形,只有充分理解p数组的由来,才可能知道它具有的变形能力。
  • 编码时间花费了很久,在动手写代码之前一定要已经思考的非常透彻,毫无逻辑缺陷再动手,这样效率是最高的。

Code:

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <iterator>
#include <cmath>
#include <cstring>
#include <cstdlib>
using namespace std;
typedef long long LL;
const int INF = 0x3fffffff, M = 10009;
vector<int> a, b, p;

string preprocess(string s)
{
    string ret = "^";
    for (int i = 0; i < s.size(); i++) {
        ret += "#";
        ret += s[i];
    }
    ret += "#$";
    return ret;
}

vector<int> Manacher(string t)
{
    vector<int> p;
    int R = 0, z = 0;
    for (int i = 1; i < t.size() - 1; i++) {
        p.push_back(R > i ?  min(R - i, p[2 * z - i - 1]) : 0);
        while (t[i + p [i - 1] + 1] == t[i - p[i - 1] - 1]) p[i - 1]++;
        if (p[i - 1] + i > R) {
            z = i;
            R = p[i - 1] + i;
        }
        if (p[i - 1] >= 1) {
            int l = (i - 1 - p[i - 1]) / 2+ 1;
            int r = (i - 1+ p[i - 1]) / 2;
            if (l == 1) a.push_back(r);
            if (r == (t.size() - 3) / 2) b.push_back(l);
        }
    }
    return p;
}

bool hw(int x, int y)
{
    int temp = y - x - 1;
    if (temp <= 0) return false;
    if ( p[((x * 2) - 1 + (y * 2) - 1) / 2] >= temp
        && (p[((x * 2) - 1 + (y * 2) - 1) / 2] - temp) % 2 == 0) return true;
    return false;
}

int main(void)
{
    int t;
    cin >> t;
    while (t--) {
        a.clear();
        b.clear();
        p.clear();
        string s;
        cin >> s;
        //for (int i = 0 ; i < 100000; i++) s += "as";
        bool ans = false;
        if (s. size() < 3) { cout << "No" << endl; continue; }
        string T = preprocess(s);
        p = Manacher(T);
        //for (int i = 0; i < p.size() ; i++) cout << p[i] << " ";
        for (int i = 0; i < a.size(); i++) {
            for (int j = 0; j < b.size(); j++) {
                if (a[i] < b[j]) {
                    int x = a[i];
                    int y = b[j];
                    if (hw(x, y)) {
                        ans = true;
                        goto l1;
                    }
                }
            }
        }
l1:     if (ans) cout << "Yes" << endl;
        else cout << "No" << endl;
    }
    return 0;
}

你可能感兴趣的:(hdu 5340 Manachers + 枚举)