标签:string
首先,在谈到Manacher算法之前,我们先来看一个小问题:给定一个字符串S,求该字符串的最长回文子串的长度.对于该问题的求解,网上解法颇多,时间复杂度也不尽相同,这里列述几种常见的解法.
bool check(string &S, int left, int right)
{
while (left < right && S[left] == S[right])
++left, --right;
return left >= right;
}
int solution(string &S)
{
int ans = 0;
for (int i = 0; i < S.size(); ++i)
for (int j = i; j < S.size(); ++j)
if (check(S, i, j))
ans = max(ans, j - i + 1);
return ans;
}int solution(string &S)
{
vector<vector<bool> > dp(2, vector<bool>(S.size(), false));
int ans = 0;
for (int i = S.size() - 1; i >= 0; --i)
{
for (int j = i; j < S.size(); ++j)
{
dp[i & 1][j] = i <= j - 2 ? (S[i] == S[j] && dp[(i + 1) & 1][j - 1]) : S[i] == S[j];
if (dp[i & 1][j])
ans = max(ans, j - i + 1);
}
}
return ans;
}int solution(string &S)
{
const int n = S.size();
int ans = 0;
for (int i = 0; i < n; ++i)
{
//for the odd case
for (int j = 0; (i - j >= 0) && (i + j < n) && S[i - j] == S[i + j]; ++j)
ans = max(ans, j << 1 | 1);
//for the even case
for (int j = 0; (i - j >= 0) && (i + 1 + j < n) && S[i - j] == S[i + 1 + j]; ++j)
ans = max(ans, 2 * j + 2);
}
return ans;
}
const int BASE = 131, N = 1e+6 + 7;
typedef unsigned long long ULL;
//rec: record forward direction hash value
//rRec:record backward direction hash value
//P: record power of BASE
ULL rec[N], rRec[N], P[N];
int Bin(int len, int end, int rEnd, int __len)
{
int l = 1, r = len;
while (l <= r)
{
int mid = l + (r - l) / 2;
ULL lHash = rec[end] - (end - mid >= 0 ? rec[end - mid] : 0) * P[mid];
ULL rHash = rRec[rEnd] - (rEnd + mid < __len ? rRec[rEnd + mid] : 0) * P[mid];
if (lHash ^ rHash)
r = mid - 1;
else
l = mid + 1;
}
return r;
}
int solution(char *S)
{
const int len = strlen(S);
P[0] = 1ULL;
//calculate power of BASE
for (int i = 1; i < =len; ++i)
P[i] = P[i - 1] * 131;
rec[0] = S[0], rRec[len - 1] = S[len - 1];
//calculate the string <span style="font-family:Microsoft YaHei;">hash </span>value
for (int i = 1, j = len - 2; i < len; ++i, --j)
rec[i] = rec[i - 1] * BASE + S[i], rRec[j] = rRec[j + 1] * BASE + S[j];
int ans = 0;
for (int i = 0; i < len; ++i)
{
int tmp;
//for the even case
tmp = Bin(min(i + 1, len - i - 1), i, i + 1, len);
ans = max(ans, tmp << 1);
//for the odd case
tmp = Bin(min(i, len - i - 1), i - 1, i + 1, len);
ans = max(ans, tmp << 1 | 1);
}
return ans;
}
上述代码有两个地方需要说明一下:1.无符号长整型溢出时,编译器会自动取模 2.关于计算P数组,如果是单case,P数组的求解可以放到solution函数中,如果是多case,P数组的求解必须放到外面,因为P数组只用计算一次就可以了.此种解法,能跑过POJ
3974和hdu 3068,感兴趣的朋友可以试试这种解法.const int N = 1e+6 + 7;
char orign[N << 1];
int P[N << 1];
int Manacher(char *S)
{
int len = strlen(S);
S[len << 1] = '#', S[len << 1 | 1] = '\0';
for (int i = len - 1; i >= 0; --i)
S[i << 1 | 1] = S[i], S[i << 1] = '#';
int center = 0, right = 0, ans = 0;
len <<= 1;
for (int i = 0; i <= len; ++i)
{
P[i] = i <= right ? min(P[2 * center - i], right - i) : 0;
while (i - P[i] - 1 >= 0 && i + P[i] + 1 <= len && S[i - P[i] - 1] == S[i + P[i] + 1])
++P[i];
if (i + P[i] > right)
right = i + P[i], center = i;
ans = max(ans, P[i]);
}
return ans;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:string
原文地址:http://blog.csdn.net/dream_you_to_life/article/details/46730111