El efecto de visualización del blog es mejor
Breve descripción del título.
Proporcione una matriz de longitud \ (n \) \ (a \) y pregunte cuántos intervalos tiene, satisfaga:
- Longitud uniforme
- Primera mitad y segunda mitad isomorfismo cíclico
\ (n \ le 5000, a_i \ le 5000 \)
Ideas
Las dos cadenas \ (a, b \) son isomorfismo cíclico, entonces \ (a \) debe dividirse en dos cadenas \ (u, v \) y luego \ (b \) se expresa como \ (v, u \) .
就 比如\ (a = \ texttt {"abcde"}, b = \ texttt {"cdeab"} \),\那么\ (a = \ texttt {"ab" + "cde"}, b = \ texttt {"cde "+" ab "} \)。
Entonces estas dos cadenas ahora son adyacentes, es decir, hay una forma continua \ (uv | vu \) . Considere enumerar la línea divisoria en el medio y luego calcular cuántos cumplen las condiciones en ambos lados. Esto puede ser capaz de usar agua de hachís, pero tenemos que pensar en una forma seria (* ▽ *)
En general, ¿qué hacemos con tales problemas de "bloque de palíndromo" ⊙ (・ ◇ ・)?
Piense en el problema de las fuerzas de código 932G . Podemos invertir la primera mitad del \ (uv \) e insertarlo uno por uno en el \ (vu \) de la segunda mitad . De esta manera, dos cadenas de palíndromo de longitud uniforme se unirán después de la inserción (/ ≧ ▽ ≦ /)
Por qué se vuelve así
Primero considere el caso de una cadena. Ahora hay un \ (u \) , suponiendo que consta de tres caracteres \ (a, b, c \) . Lo invertimos, y luego lo insertamos uno por uno, se convierte en:
\ (\ color {rojo} c \ color {negro} a \ color {rojo} b \ color {negro} b \ color {rojo} a \ color {negro} c \)
Los recién insertados se muestran en rojo, y los originales se muestran en negro. ¡Entonces descubrimos que se convirtió en un palíndromo!
Es fácil generalizar y demostrar que no importa cuánto tiempo sea, esto siempre se convertirá en una cuerda de palíndromo.
Luego considere el caso en que dos cadenas \ (u, v \) se unen. Si invertimos \ (u + v \) y los insertamos uno por uno en \ (v + u \) , ¿qué será?
Sea \ (s '\) la cadena inversa de \ (s \) . Entonces obviamente \ ((u + v) '= v' + u '\) . Después de insertarlo en \ (v + u \) , la primera cadena \ (| v | \) se convertirá primero en una cadena de palíndromo de longitud \ (2 | v | \) , seguida de \ ( | u | \) las cadenas se convertirán en una cadena de palíndromo de longitud \ (2 | u | \) . Luego, el conjunto se convierte en una cadena de palíndromo de dos pares de longitud \ (2 | v | +2 | u | \) .
Por ejemplo, \ (u = \ texttt {"ab"}, v = \ texttt {"cd"} \) , después de insertarlo, se convierte en: La fórmula explota, haga clic en mí
(Es posible que no sepa lo difícil que es esta fórmula, solo para dar un ejemplo de la imagen ... Ay, o (╥﹏╥) o)
Entonces solo necesitamos usar Manacher para contar cuántas cuerdas de palíndromo (~  ̄ ▽  ̄ ~)
Deje que \ (pre [i] \) indique la longitud máxima que se puede omitir desde \ (i \) hacia adelante, de modo que la parte omitida sea una cadena de palíndromo. Entonces \ (f [i] \) es el centro del palíndromo.
Use \ (last \) para registrar la ubicación del último prefijo de palíndromo. La posición actual es \ (i \) . Si \ ([último, i] \) es una cadena de palíndromo, o \ ([i-pre [i] + 1, i] \) es una cadena de palíndromo, entonces la \ actual (i \) es legal ~ ☆, respuesta ++.
Entonces, ¿cómo juzgar si \ ([l, r] \) es una cadena de palíndromo ⊙ (・ ◇ ・)? Establezca \ (mid = (l + r) / 2 \) y vea si \ (f [mid] \ ge (r-l + 1) / 2 \) está satisfecho .
Código
#include <bits/stdc++.h>
using namespace std;
namespace Flandre_Scarlet
{
#define N 14444
#define F(i,l,r) for(int i=l;i<=r;++i)
#define D(i,r,l) for(int i=r;i>=l;--i)
#define Fs(i,l,r,c) for(int i=l;i<=r;c)
#define Ds(i,r,l,c) for(int i=r;i>=l;c)
#define MEM(x,a) memset(x,a,sizeof(x))
#define FK(x) MEM(x,0)
#define Tra(i,u) for(int i=G.Start(u),v=G.To(i);~i;i=G.Next(i),v=G.To(i))
#define p_b push_back
#define sz(a) ((int)a.size())
#define iter(a,p) (a.begin()+p)
int I()
{
int x=0;char c=getchar();int f=1;
while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return (x=(f==1)?x:-x);
}
void Rd(int cnt,...)
{
va_list args; va_start(args,cnt);
F(i,1,cnt) {int* x=va_arg(args,int*);(*x)=I();}
va_end(args);
}
int n;
int a[N];
void Input()
{
n=I();
F(i,1,n) a[i]=I();
}
int s[N];
int f[N],pre[N];
int calc(int p)
{
int l=p,r=p+1;
int cnt=0;
while(l>=1 and r<=n) s[++cnt]=a[l],s[++cnt]=a[r],--l,++r;
F(i,0,cnt+1) f[i]=pre[i]=0;
int id=1,Max=1;
F(i,1,cnt)
{
f[i]=min(max(Max-i,0),f[id+(id-i)]);
while(i+f[i]+1<=n and i-f[i]>0 and s[i+f[i]+1]==s[i-f[i]]) ++f[i];
if (i+f[i]>=Max) Max=i+f[i],id=i;
pre[i+f[i]]=max(pre[i+f[i]],f[i]);
}
D(i,cnt,1) pre[i]=max(pre[i],pre[i+1]-1);
Ds(i,cnt,1,i-=2) pre[i]*=2;
int ans=0,last=0;
Fs(i,2,cnt,i+=2)
{
if (f[i/2]==i/2) last=i;
if (f[(i+last)/2]>=(i-last)/2 or f[(i-pre[i])/2]>=(i-pre[i])/2) ++ans;
}
return ans;
}
void Soviet()
{
int ans=0;
F(i,1,n-1) ans+=calc(i);
printf("%d\n",ans);
}
#define Flan void
Flan IsMyWife()
{
Input();
Soviet();
}
}
int main()
{
Flandre_Scarlet::IsMyWife();
getchar();getchar();
return 0;
}