Diretório de artigos
Usos do algoritmo de gerenciamento
1. Você pode encontrar o comprimento da string de palíndromo mais longa em uma string e também saber qual é a string de palíndromo mais longa.
2. Você pode descobrir quantas strings de palíndromo existem em uma string (várias strings do mesmo tipo são contadas). ps: Se você precisar de vários tipos diferentes de strings de palíndromo, poderá usar dp, árvore de palíndromo, gerenciador + hash.
complexidade de tempo
Como sempre executamos o algoritmo ingênuo ao calcular a resposta para uma posição específica, o fato de a complexidade de tempo do algoritmo ser linear não é óbvio à primeira vista.
Porém, uma análise mais detalhada mostra que o algoritmo possui complexidade linear. Na verdade, observe que cada iteração do algoritmo ingênuo aumenta r em 1 e nunca diminui enquanto o algoritmo está em execução. Essas duas observações nos dizem que o algoritmo ingênuo realizará um total de O(n) iterações.
A outra parte do algoritmo de Manacher obviamente também é linear, então a complexidade total é O(n).
formulário:[oiwiki]( Manacher - OI Wiki (oi-wiki.org)
princípio
Consulte este [blog] ( Solução do problema P3805 [[modelo]algoritmo manacher] - Quem é o blog do Ace Pigeon - Luogu Blog (luogu.com.cn)
A ideia central é usar a corda do palíndromo que foi encontrada violentamente, mais a simetria da corda do palíndromo em torno do centro, para obter rapidamente o comprimento de parte da corda do palíndromo, simplificando a escala da violência.
modelo de algoritmo
string s;//原串
char str[N];//处理后的原串
int p[N]//存储以每个点为中心的最长回文子串的半径
int ans;//代表原串中最长的回文串的长度
int sum;//代表原串中回文串的个数(同类型算多次)
int init()//init操作可以让manacher同时求解奇数个数回文串和偶数个数回文串
{
int len=s.length();
str[0]='^';
str[1]='$';
int j=2;
for (int i=0;i<len;i++)
{
str[j++]=s[i];
str[j++]='$';
}
str[j]='&';
return j;
}
int Manacher()
{
int len=change(),mid=1,r=1,ans=-1;//mid表示回文串的中心,r表示已知回文串的最右端的位置
for (int i=1;i<len;i++)//对于每个点,我们寻找以当前点为中心的最长回文子串的半径
{
if (i<r)//如果当前点的位置小于r,表示我们可以通过已知的回文串的信息,来更新当前点的信息,减少暴力的次数
p[i]=min(r-i,p[mid*2-i]);因为无法保证以当前点的对称点为中心的回文串的长度一定比当前点到最右端的位置小,所以二者取最小值,不确定的地方再交给暴力来确定
else
p[i]=1;//超过最右端时,先设为1,之后暴力找
while (s[i-p[i]]==s[i+p[i]])//暴力搜索过程
p[i]++;
if (r<i+p[i])//更新最右端
{
mid=i;
r=i+p[i];
}
sum+=p[i]/2;代表原串中回文串的个数(同类型算多次)
ans=max(ans,p[i]-1);
}
return ans;//ans代表原串中最长的回文串的长度
}
Produza o modelo de string de palíndromo mais longo
void printSub(int C, int R){//C代表中心,R代表半径
for(int i = C - R+1 ; i < C+ R;){
cout<<str[i];
i+=2;
}
}
void printmax(int k)//打印回文串
{
if(p[k] >=1)
printSub(k, p[k]);
}
[Modelo]algoritmo de gerenciamento
Descrição da pergunta
Forneça uma string SS consistindo apenas de caracteres ingleses minúsculos $ \texttt a,\texttt b,\texttt c,\ldots\texttt y,\texttt z $S , encontreSSO comprimento da corda mais longa do palíndromo em S.
O comprimento da string é nnn。
Formato de entrada
Uma linha de caracteres ingleses minúsculos a , b , c , ⋯ , y , z \texttt a,\texttt b,\texttt c,\cdots,\texttt y,\texttt zum ,b ,c ,⋯,sim ,String SScomposta por zS。 _
Formato de saída
Um número inteiro representa a resposta.
Exemplo 1
Exemplo de entrada nº 1
aaa
Exemplo de saída nº 1
3
dica
1 ≤ n ≤ 1,1 × 1 0 7 1\le n\le 1,1\vezes 10^71≤n≤1.1×1 07。
Código AC
const int N = 3e7;//因为N的范围问题,re了好几次,能开大最好开到最大,因为str需要两倍的空间
char s[N];
char str[N];
int p[N];
int init()
{
int len=strlen(s);
str[0]='!';
str[1]='#';
int j=2;
for(int i=0;i<len;i++)
{
str[j++]=s[i];
str[j++]='#';
}
s[j]='&';
return j;
}
int manacher()
{
int r=-1,mid=0;
int len=init();
int ans=0;
for(int i=0;i<len;i++)
{
if(i<r)
p[i]=min(r-i,p[2*mid-i]);
else
p[i]=1;
while(str[i-p[i]]==str[i+p[i]]) p[i]++;
if(p[i]+i>r)
{
mid=i;
r=p[i]+i;
}
ans=max(ans,p[i]-1);
}
return ans;
}
void solve()
{
scanf("%s",s);
cout<<manacher();
}
O conteúdo e os modelos do blog são apenas para estudo pessoal. Se houver algum erro, corrija-o!