【题目描述】
【思路】
假设现在有一个位置 p o s pos pos ,其前缀已经出现一次即 [ 0 , p o s − 1 ] [0,pos-1] [0,pos−1] 这个前缀已经出现了一次,现在考虑一下 n e x t [ p o s ] next[pos] next[pos] 的意义,其实就是包含在 [ 0 , p o s − 1 ] [0,pos-1] [0,pos−1] 这个前缀里面的前缀(前缀针对整个字符串而言,并非 [ 0 , p o s − 1 ] [0,pos-1] [0,pos−1] 这个子串),也就是如果我们能够知道一个前缀出现的次数,那么包含在这个前缀里面的前缀也应当又出现了一次,所以只要跑一遍 KMP 得到 n e x t next next 数组,然后对每一个前缀出现的次数都叠加到其包含的前缀当中去,即状态转移方程 d p [ n e x t [ i ] ] + = d p [ i ] dp[next[i]] += dp[i] dp[next[i]]+=dp[i] ( d [ i ] d[i] d[i] 代表长度为 i i i 的前缀出现的次数),整个过程应该是逆推的
#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;
}