后缀自动机

本文深入探讨了后缀自动机的构建与应用,通过代码示例详细解释了如何使用后缀自动机识别字符串中的所有子串,并计算不同子串的数量。文章提供了完整的C++实现代码,包括初始化、扩展节点等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

后缀自动机

  1. 后缀自动机 可以识别所有子串

  2. 求本质不同的子串 len[i]−link[len[i]]len[i]-link[len[i]]len[i]link[len[i]]

``

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e6+10;
typedef long long ll;
ll ans=0;
ll dp[MAXN<<1];
struct SAM{
	int sz,last;
	int link[MAXN<<1],trans[MAXN<<1][26],len[MAXN<<1];
	
	SAM(){
		sz=last=0;len[0]=0;link[0]=-1;
	}
	void init(){
		sz=last=0;len[0]=0;link[0]=-1;
		memset(trans,0,sizeof trans);
	}
	void extend(int id){
		int cur=++sz,p;
		len[cur]=len[last]+1;dp[cur]=1;
		for(p=last;p!=-1 && !trans[p][id];p=link[p]) trans[p][id]=cur;
		
		if(p==-1) link[cur]=0;
		else {
			int q=trans[p][id];
			if(len[p]+1==len[q]) link[cur]=q; ////1.
			else{
				int clone=++sz;
				len[clone]=len[p]+1;
				link[clone]=link[q];
				memcpy(trans[clone],trans[q],26*sizeof(int));//字符数 
				for(;p!=-1 && trans[p][id]== q ;p=link[p]) trans[p][id]=clone;
				
				link[q]=link[cur]=clone;//
			}		
		}
		last=cur;
	} 
} T;
int n;
string str;
vector<int> e[MAXN<<1];
void dfs(int u){
//	dp[u]=1;
	for(int i=0;i<e[u].size();i++){
		int v=e[u][i];
		dfs(v);
		dp[u]+=dp[v];
		
	}
//	if(dp[u]>1) ans=max(ans,1ll*(dp[u])*T.len[u]);
}

int main(){
	cin>>str;n=str.size(); 
	
	for(int i=0;i<n;i++) T.extend(str[i]-'a');
	
	for(int i=1;i<=T.sz;i++){
		e[T.link[i]].push_back(i);
	}
	ans=0;
	dfs(0);
//	for()
	
	for(int i=1;i<=T.sz;i++){
		if(dp[i]>1) ans=max(ans,1ll*(dp[i])*T.len[i]);
	}
	
	cout<<ans<<endl; 
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值