前置知识
解法
一个子串出现至少 \(2\) 次等价于有至少连续 \(2\) 个后缀以这个子串作为公共前缀。
进行一次后缀排序后,有 \(\max\limits_{i=1}^{|s|} \{ height_{i} \}\) 即为所求。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define sort stable_sort
#define endl '\n'
int sa[5010],rk[10010],oldrk[10010],id[5010],cnt[5010],key[5010],height[5010];
char s[5010];
int val(char x)
{
return (int)x;
}
void counting_sort(int n,int m)
{
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=n;i++)
{
cnt[key[i]]++;
}
for(int i=1;i<=m;i++)
{
cnt[i]+=cnt[i-1];
}
for(int i=n;i>=1;i--)
{
sa[cnt[key[i]]]=id[i];
cnt[key[i]]--;
}
}
void init_sa(char s[],int len)
{
int m=127,tot=0,num=0,i,j,w;
for(i=1;i<=len;i++)
{
rk[i]=val(s[i]);
id[i]=i;
key[i]=rk[id[i]];
}
counting_sort(len,m);
for(w=1;tot!=len;w<<=1,m=tot)
{
num=0;
for(i=len;i>=len-w+1;i--)
{
num++;
id[num]=i;
}
for(i=1;i<=len;i++)
{
if(sa[i]>w)
{
num++;
id[num]=sa[i]-w;
}
}
for(i=1;i<=len;i++)
{
key[i]=rk[id[i]];
}
counting_sort(len,m);
for(i=1;i<=len;i++)
{
oldrk[i]=rk[i];
}
tot=0;
for(i=1;i<=len;i++)
{
tot+=(oldrk[sa[i]]!=oldrk[sa[i-1]]||oldrk[sa[i]+w]!=oldrk[sa[i-1]+w]);
rk[sa[i]]=tot;
}
}
for(i=1,j=0;i<=len;i++)
{
j-=(j>=1);
while(s[i+j]==s[sa[rk[i]-1]+j])
{
j++;
}
height[rk[i]]=j;
}
}
int main()
{
int t,n,ans,i,j;
cin>>t;
for(j=1;j<=t;j++)
{
ans=0;
cin>>(s+1);
n=strlen(s+1);
init_sa(s,n);
for(i=1;i<=n;i++)
{
ans=max(ans,height[i]);
}
cout<<ans<<endl;
}
return 0;
}
后记
强化版:luogu P2852 [USACO06DEC] Milk Patterns G
标签:5010,cnt,int,题解,num,Editor,UVA1223,sa,id From: https://www.cnblogs.com/The-Shadow-Dragon/p/18118390