[每日一题2020.06.26]最大回文子串 manachar

题目 :

image-20200626190450694

image-20200626190505662

就是一个求最大回文子串的模板题 :

方法一 : 中心扩展 时间复杂度\(O(n^2)\)

之前在leetcode上就是用的中心扩展做的, 勉强过了

中心扩展思路很简单, 就是遍历一遍字符串, 然后对于每一个字符都向左右扩展求最大回文串

这道题的中心扩展代码 :

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2000000 + 5;
#define debug(x) \
(void)(cerr << "L" << __LINE__\
			<< " : " << #x << " = " \
			<< (x) << endl )


int judge(string s) { 
	string ss = "";
	for (int i = 0; i < s.size(); ++i) {
		ss += '#';
		ss += s[i];
	}
	ss += '#';
	int ptr = 0;
	int ans = -1;
	while (ptr < ss.size() - 1) {
		int k = 1;
		int sum = ( ss[ptr] == '#' ? 0 : 1 );
		while (ptr + k < ss.size() && ptr - k >= 0 && ss[ptr + k] == ss[ptr - k])
		{
			sum += ( ss[ptr + k] == '#' ? 0 : 2 );
			k++;
		}
		ptr++;
		ans = max(ans, sum);
	}
	return ans;
}



int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
 	string s;
 	int i = 1;
 	while (cin >> s && s != "END") {
 		cout << "Case " << i++ << ": " << judge(s) << endl;
 	}   
    return 0;
}

由于时间复杂度太高, 这题TLE, 被迫学习manachar

方法二 : manachar 时间复杂度\(O(n)\)

因为这个算法有点牛逼, 我直接另开一篇博客记录一下

本质就是利用了回文串的对称性, 避免了中心扩展的许多重复操作

#include<iostream>
#include<string>
#include<string.h>
using namespace std;
const int maxn = 2000000 + 5;
int lens[maxn];

void reIO() {
#ifndef ROCCOSHI
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
}

#define debug(x) \
(void)(cerr << "L" << __LINE__\
			<< " : " << #x << " = " \
			<< (x) << endl )

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


int manachar(string s) {
	int mx = 0;
	int pos = 0;
	int ans = -1;
	for (int ptr = 1; ptr < s.size() - 1; ++ptr) {
		if (ptr < mx) 
			lens[ptr] = min (lens[2 * pos - ptr], mx - ptr);
		else
			lens[ptr] = 1;
		while (s[ptr - lens[ptr]] == s[ptr + lens[ptr]])
			lens[ptr]++;
		if (mx < ptr + lens[ptr]) { 
			mx = ptr + lens[ptr];
			pos = ptr;
		}
  		ans = max (ans, lens[ptr] - 1);
	}
	return ans;
}



int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	reIO();
	string s;
	int i = 1;
	while (cin >> s && s != "END") {
		s = expand(s);
		cout << "Case " << i++ << ": " << manachar(s) << endl;
	}
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/roccoshi/p/13196167.html