題目大意
給定一個字串集爲
數據範圍
題解
這道題感覺非常的好玩,不知道爲什麼要強行說是一個分類討論題。。。
首先我們將最終得到的最長迴文串的迴文中心進行分類討論:
1. 迴文中心沒有被排序
2. 迴文中心是排序後調過來的,並且存在某個前綴,使得其沒有被排序
注意上面的分類沒有考慮到一種迴文串整個都是被排序了得情況,我們可以最後將
接下來我們考慮排序的區間都是在右邊的,也就是不會對迴文串的前面排序,對於前面排序的情況我們可以整個串取反來做。
迴文中心沒有被排序
先枚舉迴文中心,設爲位置i
設
那麼我們相當於可以設兩個指針
但有一個值得注意的小細節,就是假如當前
這裏的複雜度爲
迴文中心被排序
設最大的沒有被排序的位置爲
關鍵還是代碼吧。。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 3005;
int F[MAXN][MAXN],S[MAXN],N,C;
void Get_F()
{
memset(F,0,sizeof F);
//F[i][j] max(S[i - l + 1..i] = S[j..j + l - 1])
for(int i = 1;i <= N;i ++)
for(int j = N;j >= i;j --)
if (F[i - 1][j + 1] >= 0 && S[i] == S[j]) F[i][j] = F[i - 1][j + 1] + 1;
}
int TreatR(int lr,int cent,int rl)
{
if (!lr || rl > N) return 0;
static int Cnt[MAXN],Cur[MAXN],Stack[MAXN][2];
int top = 0;
memset(Cnt,0,sizeof Cnt),memset(Cur,0,sizeof Cur);
for(int u = lr;u;u --)
{
++ Cnt[S[u]];
if (S[u] >= Stack[top][0]) Stack[++ top][0] = S[u],Stack[top][1] = Cnt[S[u]]; else
break;
}
int MiLen = 0,NeedLen = 0,LimLen = top,tmp = 0;
for(int rr = rl;rr <= N;rr ++)
{
if (S[rr] < cent) break; else
if (S[rr] == cent) ++ MiLen; else
{
++ Cur[S[rr]];
if (Cnt[S[rr]] >= Cur[S[rr]])
{
while (NeedLen + 1 <= top)
{
int val = Stack[NeedLen + 1][0];
if (Cur[val] >= Stack[NeedLen + 1][1]) ++ NeedLen; else break;
}
} else
{
while (LimLen)
{
int val = Stack[LimLen][0];
if (val > S[rr]) -- LimLen; else break;
}
}
}
int cl = min(NeedLen,LimLen);
tmp = max(tmp,cl * 2 + MiLen);
if (rr - rl + 1 == cl + MiLen) tmp = max(tmp,cl * 2 + MiLen + 2 * F[lr - cl][rl + cl + MiLen]);
}
return tmp;
}
int Calc()
{
Get_F();
//calc middle as a position
int tmp = 0;
for(int i = 1;i <= N;i ++)
{
int lr = i,rl = i,d = F[i][i];
lr -= d,rl += d;
tmp = max(tmp,TreatR(lr,-1,rl) + 2 * d - 1);
}
//calc middle as a middle
for(int i = 1;i < N;i ++)
{
int lr = i,rl = i + 1,d = F[i][i + 1];
lr -= d,rl += d;
tmp = max(tmp,TreatR(lr,-1,rl) + 2 * d);
}
//calc those when the sorted make difference
for(int i = 1;i <= N;i ++)
{
int cent = -1;
for(int j = i + 1;j <= N;j ++)
if (S[j] < S[i]) {cent = S[j];break;}
tmp = max(tmp,TreatR(i,cent,i + 1));
}
return tmp;
}
void Work()
{
static int Bak[MAXN];
for(int i = 1;i <= N;i ++) scanf("%d", &S[i]);
int ans = Calc();
memcpy(Bak,S,sizeof Bak);
for(int i = 1;i <= N;i ++) S[i] = C - S[i] + 1;
reverse(S + 1,S + N + 1);
ans = max(ans,Calc());
memcpy(Bak,S,sizeof Bak);
int c = 0,cr = 0;
sort(S + 1,S + N + 1);
for(int i = 1;i <= N;i ++)
if (S[i] != S[i - 1]) ans = max(ans,cr),cr = 1; else ++ cr;
ans = max(ans,cr);
printf("%d\n", ans);
}
int main()
{
while (scanf("%d%d", &N, &C) != EOF) Work();
return 0;
}