P5028 Annihilate
题目传送门
思路
算是一道简单的
首先,注意到
根据
注意到如果我们枚举到排名为
如果出题人不卡空间,那么可以直接上
最后就是
时间复杂度
代码
#include<bits/stdc++.h>
using namespace std;
int const N=3e6+10;
char k[N];
int rk[N],w,ans[105][105],minx[105],frm[N],sum[N],oldrk[N],sa[N],height[N];
inline bool cmp(int x,int y){return rk[x]==rk[y]?rk[x+w]<rk[y+w]:rk[x]<rk[y];}
inline void SA(string s){
int n=s.length();s=" "+s;
for (int i=1;i<=n;++i) k[i]=s[i];
sort(k+1,k+n+1);
for (int i=1;i<=n;++i) rk[i]=lower_bound(k+1,k+n+1,s[i])-k,sa[i]=i;
for (w=1;w<n;w<<=1){
sort(sa+1,sa+n+1,cmp);
for (int i=1;i<=n;++i) oldrk[i]=rk[i];
for (int p=0,i=1;i<=n;++i)
if (oldrk[sa[i]]==oldrk[sa[i-1]] && oldrk[sa[i]+w]==oldrk[sa[i-1]+w]) rk[sa[i]]=p;
else rk[sa[i]]=++p;
}
for (int i=1;i<=n;++i) rk[sa[i]]=i;
int k=0;
for (int i=1;i<=n;++i){
if (k) --k;int j=sa[rk[i]-1];
while (j+k<=n && i+k<=n && s[i+k]==s[j+k]) ++k;
height[rk[i]]=k;
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int n;cin>>n;string ss="";
for (int i=1;i<=n;++i){
string s;cin>>s;
int len=s.length();
s=" "+s;for (int j=1;j<=len;++j)
ss+=s[j],frm[ss.length()]=i;
ss+=char(i+26);
}
SA(ss);int m=ss.length();
for (int i=2;i<=m;++i){
for (int j=1;j<=n;++j) minx[j]=min(minx[j],height[i]);
minx[frm[sa[i-1]]]=height[i];
int now=frm[sa[i]];
for (int j=1;j<=n;++j) ans[now][j]=ans[j][now]=max(ans[now][j],minx[j]);
}
for (int i=1;i<=n;++i,cout<<'\n')
for (int j=1;j<=n;++j)
if (i^j) cout<<ans[i][j]<<' ';
return 0;
}