标签:本质 出现 bool bsp bre init 一个 次数 namespace
哇哦~想不到我有生之年竟然能够做出字符串的题目ヾ(??▽?)ノ虽然这题比较裸但依然灰常开心!
首先有一个棒棒的性质:本质不同的回文串最多有 O(n) 个。首先 manacher 把它们都找出来,然后问题就变成了给定 n 个子串,求它们在原串中出现的次数。求出 height 然后二分一下即可(这个好像是SA 的基础操作?)。
#include using namespace std;
#define maxn 601550
#define CNST 22
int n, N, m, p1[maxn], p2[maxn], rk[maxn], bits[CNST];
int p[maxn], rec[maxn], t[maxn], y[maxn], Log[maxn];
int num[maxn], SA[maxn], ST[maxn][CNST];
long long ans;
char a[maxn], s[maxn];
void pre()
{
s[0] = s[1] = ‘#‘; s[2 * n + 2] = ‘?‘;
for(int i = 0; i 2 + 2] = a[i], s[i * 2 + 3] = ‘#‘;
N = n * 2 + 2;
}
void Up(int &x, int y) { x = (x > y) ? x : y; }
void manacher()
{
int mid = 0, mr = 0;
for(int i = 0; i )
{
if(i 1) - i], p[mid] + mid - i);
else p[i] = 1; Up(rec[i + p[i] - 1], p[i]);
while(s[i + p[i]] == s[i - p[i]])
{
p[i] ++;
Up(rec[i + p[i] - 1], p[i]);
}
if(p[i] + i - 1 > mr) mr = p[i] + i - 1, mid = i;
}
}
//SA
void Rsort(int *p, int *x, int *id)
{
for(int i = 1; i 0;
for(int i = 1; i ;
for(int i = 1; i 1];
for(int i = n; i >= 1; i --) x[t[p[id[i]]] --] = id[i];
}
bool cmp(int x, int y) { return y && (p1[x] == p1[y] && p2[x] == p2[y]); }
void Get_SA()
{
m = 128;
for(int k = 0; bits[k] )
{
for(int i = 1; i )
p1[i] = rk[i], p2[i] = (i + bits[k] 0;
Rsort(p2, y, num); Rsort(p1, SA, y);
for(int i = 1, p = 0; i )
rk[SA[i]] = cmp(SA[i - 1], SA[i]) ? p : ++ p;
if(m >= n) break;
}
}
void Get_Height()
{
for(int i = 1, k = 0; i )
{
if(k) k --;
int j = SA[rk[i] - 1];
while(max(i, j) + k - 1 1] == a[i + k - 1]) k ++;
ST[rk[i]][0] = k;
}
}
void Build()
{
for(int j = 1; j )
for(int i = 1; i + bits[j] - 1 )
ST[i][j] = min(ST[i][j - 1], ST[i + bits[j - 1]][j - 1]);
}
int RMQ(int x, int y)
{
if(y x) swap(x, y);
int k = Log[y - x + 1];
return min(ST[x][k], ST[y - bits[k] + 1][k]);
}
int Query(int x, int len)
{
int l = 1, r = rk[x], ans2 = rk[x], ans1 = rk[x] + 1;
while(l r)
{
int mid = (l + r) >> 1;
if(RMQ(rk[x], mid) >= len) ans1 = mid, r = mid - 1;
else l = mid + 1;
}
ans1 --; l = rk[x] + 1, r = n;
while(l r)
{
int mid = (l + r) >> 1;
if(RMQ(rk[x] + 1, mid) >= len) ans2 = mid, l = mid + 1;
else r = mid - 1;
}
return ans2 - ans1 + 1;
}
void init()
{
Log[0] = -1; for(int i = 1; i > 1] + 1;
bits[0] = 1; for(int i = 1; i 1] 1;
for(int i = 1; i i;
}
int main()
{
init();
scanf("%s", a); n = strlen(a);
pre(); manacher();
for(int i = 1; i 1];
Get_SA(); Get_Height(); Build();
for(int i = 1; i )
{
if(s[i] == ‘#‘) continue;
int r = (i - 2) >> 1;
int l = r - rec[i] + 1; r ++, l ++;
int t = Query(l, r - l + 1);
ans = max(ans, 1ll * t * (r - l + 1));
}
printf("%lld\n", ans);
return 0;
}
【题解】APIO2014回文串
标签:本质 出现 bool bsp bre init 一个 次数 namespace
原文地址:https://www.cnblogs.com/twilight-sx/p/9990465.html