You are given a string s, consisting of lowercase English letters. Find the longest string, t, which satisfies the following conditions:
样例
input:
5
a
abcdfdcecba
abbaxyzyx
codeforces
acbba
output:
a
abcdfdcba
xyzyx
c
abba
首先前后一一匹配,比方说abccbba,找出前缀ab后缀ba,剩下的ccb找一个最长回文前缀(cc),后缀(b)选最长的
最长回文前缀问题可以用字符串哈希解决,求一遍正向哈希,再求一遍倒着的哈希,如果是回文hash值相同,这里用的是BDKRHash,它可以O(1)求子串hash值,另外hash是非完美算法,可以在O(n)检验一下是不是回文串
#include
#include
using namespace std;
typedef unsigned long long LL;
#define base 33
LL p[1000100];
LL h1[1000100],h2[1000100];
inline LL gethash1(int l,int r) {
LL tp = l?h1[l-1]:0;
return h1[r] - tp*p[r-l+1];
}
inline LL gethash2(int l,int r) {
LL tp = l?h2[l-1]:0;
return h2[r] - tp*p[r-l+1];
}
bool Is_palindrome(string s) {
for (int i = 0; i < s.size()/2; i++)
if (s[i] != s[s.size()-1-i]) return 0;
return 1;
}
string find(string s) {
string ans = "";
int len = s.size();
if (len == 0) return ans;
for (int i = 0; i < len; i++) {
if (i == 0) h1[i] = s[i];
else h1[i] = h1[i-1]*base+s[i];
// cout << h1[i] << " ";
}
// puts("");
// 12345
for (int i = 0; i < len; i++) {
if (i == 0) h2[i] = s[len-i-1];
else h2[i] = h2[i-1]*base+s[len-i-1];
// cout << h2[i] << " ";
}
// 54321
// puts("");
//cout << gethash1(2,2) << " " << gethash2 (2,2) << "def\n";
// int a = 0,b = 0;
for (int i = len-1; i >= 0; i--) {
if (gethash1(0,i) == gethash2(len-1-i,len-1) && Is_palindrome(s.substr(0,i+1))) return s.substr(0,i+1);
// if (gethash1(len-1-i,len-1) == gethash2(0,i)) return s.substr(len-1-i,i+1);
// cout << i << "\n";
}
return ans;
}
void work() {
string s;
cin >> s;
string comm = "";
int i;
for (i = 0; i < s.size()/2; i++)
if (s[i] == s[s.size()-1-i]) comm += s[i];
else break;
s = s.substr(i,s.size()-i-i);
string ss = "";
for (int i = s.size()-1; i>=0; i--) ss += s[i];
string s1 = find(s),s2 = find(ss);
cout << comm << (s1.size()>s2.size()?s1:s2);
for (int i = comm.size()-1; i >= 0; i--)
cout << comm[i];
puts("");
}
int main() {
p[0] = 1;
for (int i = 1; i <= 1000000; i++)
p[i] = p[i-1]*base;
int n;
cin >> n;
while (n--) {
work();
}
return 0;
}