广义后缀自动机例题
时间:2021-08-11
本文章向大家介绍广义后缀自动机例题,主要包括广义后缀自动机例题使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
以每个叶子节点为开头进行dfs遍历,将遍历到的串全部加入建立广义SAM,结果即为本质不同的字符串个数
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#define int long long
using namespace std;
const int maxn=2e6+10;
int n,m,tot,len[maxn],fa[maxn],ch[maxn][26],c;
int head[maxn<<1],nex[maxn<<1],to[maxn<<1];
int cnt[maxn];
char s[maxn];
int vis[maxn];
int res;
int col[maxn];
int k=1;
int ecnt;
void add(int x,int y) {
to[++ecnt]=y;
nex[ecnt]=head[x];
head[x]=ecnt;
}
int Ins(int c,int last) {
int p=last;
if(ch[p][c]) {
int q=ch[p][c];
if(len[p]+1==len[q]) {
return q;
} else {
int nq=++tot;
len[nq]=len[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[nq]));
fa[nq]=fa[q];
fa[q]=nq;
for(; p&&ch[p][c]==q; p=fa[p])ch[p][c]=nq;
return nq;
}
}
int np=++tot;
len[np]=len[p]+1;
for(; p&&!ch[p][c]; p=fa[p])ch[p][c]=np;
if(!p)fa[np]=1;
else {
int q=ch[p][c];
if(len[p]+1==len[q])fa[np]=q;
else {
int nq=++tot;
vis[nq]=k;
len[nq]=len[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[nq]));
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
for(; p&&ch[p][c]==q; p=fa[p])ch[p][c]=nq;
}
}
return np;
}
int id[maxn];
inline void prepare() {
for (int i=1; i<=tot; i++) cnt[len[i]]++;
for (int i=1; i<=tot; i++) cnt[i]+=cnt[i-1];
for (int i=1; i<=tot; i++) id[cnt[len[i]]--]=i;
for (int i=tot; i>=1; i--) {
int X=id[i];
if (vis[fa[X]]==0) vis[fa[X]]=vis[X];
else if (vis[fa[X]]!=vis[X]) vis[fa[X]]=-1;
}
}
void dfs(int x,int fa,int last) {
int tmp=Ins(col[x],last);
for(int i=head[x]; i; i=nex[i]) {
int y=to[i];
if(y==fa)continue;
dfs(y,x,tmp);
}
}
int in[maxn];
signed main() {
std::ios::sync_with_stdio(false);
int n,c;
cin>>n>>c;
tot=1;
for(int i=1; i<=n; i++) {
cin>>col[i];
}
for(int i=1; i<n; i++) {
int x,y;
cin>>x>>y;
in[x]++;
in[y]++;
add(x,y);
add(y,x);
}
for(int i=1; i<=n; i++) {
if(in[i]==1)
dfs(i,i,1);
}
for(int i=2; i<=tot; i++) {
res+=len[i]-len[fa[i]];
}
cout<<res<<endl;
}
原文地址:https://www.cnblogs.com/ddsszdnt/p/15128903.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【排序】堆排序
- redis灵魂拷问:怎样搭建一个哨兵主从集群
- 是时候给你的鼠标指针更换样式换下风格体验了!如何卸载与安装鼠标指针?
- Linux设置虚拟内存
- SSM 单体框架 - 教育平台后台管理系统:接口文档
- java学习应用篇|使用环境变量做一些工具
- 【Java8新特性】06 新的日期和时间:LocalDate LocalTime LocalDateTime
- UNSAFE和Java 内存布局
- 【玩转Redis面试第1讲】Redis数据结构和常用命令速记
- SSM 单体框架 - 教育平台后台管理系统:课程模块
- 【玩转Redis面试第2讲】面试官再问Redis事务把这篇文章扔给他
- SSM 单体框架 - 教育平台后台管理系统:Maven 进阶使用
- SSM 单体框架 - 教育平台后台管理系统:广告和用户模块开发
- 杀死进程
- SSM 单体框架 - 教育平台后台管理系统:权限模块开发