栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

YbtOJ「字符串算法」第3章 后缀自动机 I. 独特子串 题解--zhengjun

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

YbtOJ「字符串算法」第3章 后缀自动机 I. 独特子串 题解--zhengjun

题目大意

给定 n n n 个字符串,求出每个字符串只属于该字符串的本质不同的非空子串的个数。

思路

如果没有做过这道 SA 入门题《不同子串个数》,那么请先了解这道题的 SA 做法。

首先老套路,把所有字符串拼接在一起。

然后单独考虑一个字符串 i i i,首先求出这个字符串的每一个后缀有多少个前缀没有在其他字符串中出现过,假设当前在求排名为 i i i 的后缀的值,那么就需要知道排名在 i i i 前面的第一个后缀 s a j sa_j saj​ 与后缀 s a i sa_i sai​ 不在同一个字符串里(即求出最大的 p r e i = j pre_i=j prei​=j,使得 j ≤ i , i d s a j ≠ i d s a i jle i,id_{sa_j}ne id_{sa_i} j≤i,idsaj​​​=idsai​​, i d id id 表示第 i i i 号位置的字符是哪个字符串的),然后求出最小的 n e x i = j nex_i=j nexi​=j,使得 j ≥ i , i d s a j ≠ i d s a i jge i,id_{sa_j}ne id_{sa_i} j≥i,idsaj​​​=idsai​​,这一步可以线性递推,这样,这个后缀的在其他字符串中出现过的前缀个数就是 max ⁡ { L C P ( i , s a p r e i ) , L C P ( i , s a n e x i } max{LCP(i,sa_{pre_i}),LCP(i,sa_{nex_i}} max{LCP(i,saprei​​),LCP(i,sanexi​​}。

接着,只需要向刚刚的那道题一样处理,减去每个后缀与排名在它前一个的后缀的公共前缀减掉就好了。

代码
#include
using namespace std;typedef long long ll;const int N=2e5+10,K=log2(N)+2;string a;ll ans;
int n,m,k,s[N],rk[N],sa[N],old[N<<1],cnt[N],p[N],id[N],h[N],st[N],ed[N],pos[N],t[N],lg[N],f[K][N],pre[N],nex[N];
void getsa(int n,int m){
	for(int i=1;i<=n;i++)cnt[rk[i]=s[i]]++;for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1];
	for(int i=n;i>=1;i--)sa[cnt[rk[i]]--]=i;for(int i=1;i<=m;i++)cnt[i]=0;for(int len=1,k;len==1||m^n;m=k,len<<=1){
		k=0;for(int i=n-len+1;i<=n;i++)p[++k]=i;for(int i=1;i<=n;i++)if(sa[i]>len)p[++k]=sa[i]-len;
		for(int i=1;i<=n;i++)cnt[id[i]=rk[p[i]]]++;for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1];
		for(int i=n;i>=1;i--)sa[cnt[id[i]]--]=p[i];for(int i=1;i<=m;i++)cnt[i]=0;for(int i=1;i<=n;i++)old[i]=rk[i];
		k=0;for(int i=1;i<=n;i++)rk[sa[i]]=old[sa[i]]==old[sa[i-1]]&&old[sa[i]+len]==old[sa[i-1]+len]?k:++k;
	}for(int i=1,k=0;i<=n;i++){if(k)k--;while(max(i,sa[rk[i]-1])+k<=n&&s[i+k]==s[sa[rk[i]-1]+k])k++;h[rk[i]]=k;}h[1]=0;
}
void init(){
	for(int i=2;i<=m;i++)lg[i]=lg[i>>1]+1;for(int i=1;i<=m;i++)f[0][i]=h[i];
	for(int i=1;(1<l=rk[l];r=rk[r];if(l>r)swap(l,r);int k=lg[r-l++];return min(f[k][l],f[k][r-(1<
	k=128;scanf("%d",&n);for(int i=1;i<=n;i++){cin>>a;st[i]=m+1;for(char c:a)s[++m]=c,pos[m]=i;s[++m]=++k;pos[m]=i;ed[i]=m;}
	getsa(m,k);init();for(int i=1;i<=m;i++)if(pos[sa[i]]==pos[sa[i-1]])pre[i]=pre[i-1];else pre[i]=i-1;
	for(int i=m;i>=1;i--)if(pos[sa[i]]==pos[sa[i+1]])nex[i]=nex[i+1];else nex[i]=i+1;for(int i=1;i<=n;i++){
		ans=1ll*(ed[i]-st[i]+1)*(ed[i]-st[i])/2;for(int j=st[i];j<=ed[i];j++)if(pre[rk[j]])t[j]=LCP(j,sa[pre[rk[j]]]);
		for(int j=st[i];j<=ed[i];j++)if(nex[rk[j]])t[j]=max(t[j],LCP(j,sa[nex[rk[j]]]));for(int j=st[i];j 
如有问题请指出,谢谢–zhengjun
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/931394.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号