一个字符串的前缀是指包含该字符第一个字母的连续子串,例如:abcd的所有前缀为a, ab, abc, abcd。
给出一个字符串S,求其所有前缀中,字符长度与出现次数的乘积的最大值。
例如:S = "abababa" 所有的前缀如下:
"a", 长度与出现次数的乘积 1 * 4 = 4,
"ab",长度与出现次数的乘积 2 * 3 = 6,
"aba", 长度与出现次数的乘积 3 * 3 = 9,
"abab", 长度与出现次数的乘积 4 * 2 = 8,
"ababa", 长度与出现次数的乘积 5 * 2 = 10,
"ababab", 长度与出现次数的乘积 6 * 1 = 6,
"abababa", 长度与出现次数的乘积 7 * 1 = 7.
其中"ababa"出现了2次,二者的乘积为10,是所有前缀中最大的。
Input
输入字符串S, (1 <= L <= 100000, L为字符串的长度),S中的所有字符均为小写英文字母。
Output
输出所有前缀中字符长度与出现次数的乘积的最大值。
Input示例
abababa
Output示例
10
f[i]=S[0...i]在S中出现的次数
f[i]=∑i+j<nj=0(S[0...i]与S[j...j+i]的公共前缀长度>=i+1)
=> f[i]=∑j<=n−i−1j=0(S[0...i]与suffix[j]的公共前缀长度>=i+1) | suffix[j]为S以j开始的后缀
而拓展KMP中,S的Next[i]=suffix[i]与S的最长公共前缀长度
=> f[i]=∑j<=n−i−1j=0(Next[j]>=i+1)
sum[i]=∑nj=iNext[j]
ans=max(sum[i]∗(i+1))
#include<stdio.h>
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define MEM(a,x) memset(a,x,sizeof(a))
#define lowbit(x) ((x)&-(x))
using namespace std;
const int inf=0x3f3f3f3f;
const int N = 100000 + 5;
void pre_EKMP(char x[],int m,int next[])
{
next[0]=m;
int j=0;
while(j+1<m && x[j]==x[j+1])j++;
next[1]=j;
int k=1;
for(int i=2;i<m;i++)
{
int p=next[k]+k-1;
int L=next[i-k];
if(i+L<p+1)next[i]=L;
else
{
j=max(0,p-i+1);
while(i+j<m && x[i+j]==x[j])j++;
next[i]=j;
k=i;
}
}
}
char str[N];
int Next[N];
int sum[N];
int main()
{
//freopen("/home/lu/code/r.txt","r",stdin);
while(~scanf("%s",str)){
int n=strlen(str);
pre_EKMP(str,n,Next);
for(int i=0;i<n;++i){
sum[Next[i]]+=1;
}
ll ans=n;
for(int i=n-1;i>=0;--i){
sum[i]+=sum[i+1];
ans=max(ans,(ll)i*sum[i]);
}
printf("%lld\n",ans);
}
return 0;
}