【题目描述】
【思路】
假设现在有一个位置
,其前缀已经出现一次即
这个前缀已经出现了一次,现在考虑一下
的意义,其实就是包含在
这个前缀里面的前缀(前缀针对整个字符串而言,并非
这个子串),也就是如果我们能够知道一个前缀出现的次数,那么包含在这个前缀里面的前缀也应当又出现了一次,所以只要跑一遍 KMP 得到
数组,然后对每一个前缀出现的次数都叠加到其包含的前缀当中去,即状态转移方程
(
代表长度为
的前缀出现的次数),整个过程应该是逆推的
#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
char p[maxn];
int nxt[maxn],lenp;
long long dp[maxn];
void getnext(){
nxt[0]=-1;
int j=0,k=-1;
while(j<lenp){
if(k==-1 || p[k]==p[j]){
++j;
++k;
nxt[j]=k;
}
else k=nxt[k];
}
}
int main(){
scanf("%s",p);
lenp=strlen(p);
getnext();
for(int i=1;i<=lenp;++i) dp[i]=1;
for(int i=lenp;i>=1;--i) dp[nxt[i]]+=dp[i];
long long ans=0;
for(int i=1;i<=lenp;++i) ans=max(ans,(long long)i*dp[i]);
printf("%lld\n",ans);
return 0;
}