当前位置:网站首页>[SAM模板题] P3975 [TJOI2015] 弦论
[SAM模板题] P3975 [TJOI2015] 弦论
2022-07-30 22:47:00 【HeartFireY】
题目思路
对原串建立 S A M SAM SAM,然后分情况考虑:
- t = 0 t = 0 t=0,代表本质不同即为不同,那么我们需要对每个 S A M SAM SAM节点 u u u维护 u u u能够到达的点的数量,即为经过 u u u的本质不同的子串的数量。
- t = 1 t = 1 t=1,代表位置不同即为不同,那么我们考虑对于每个节点 u u u计算经过该点位置不同的子串数量。那么我们可以想到这需要先求串 s s s的出现次数,也就是 e n d p o s ( s ) endpos(s) endpos(s)的大小,而根到 u u u表示的串的 e n d p o s endpos endpos大小为 p a r e n t t r e e parent\ tree parent tree上 u u u的子树中的前缀点的数量
不难发现,我们可以维护一个 d p [ u ] dp[u] dp[u]表示不同限制下的子串数目,以及每个点的点权。对于 t = 0 t = 0 t=0,所有点的点权都是 1 1 1,否则先 d f s dfs dfs求子树大小作为点权,然后 d f s dfs dfs求答案即可。
#include <bits/stdc++.h>
#pragma gcc optimize("O2")
#pragma g++ optimize("O2")
#define int long long
#define endl '\n'
using namespace std;
const int N = 1e6 + 10, MOD = 1e9 + 7;
int dp[N], siz[N];
struct SAM{
int ch[N << 1][26], fa[N << 1], len[N << 1], vis[N << 1];
int last, tot;
SAM(): last(1), tot(1) {
}
inline void extend(int x){
//*单字符扩展
int p = last, np = last = ++tot;
len[np] = len[p] + 1, vis[np] = dp[np] = siz[np] = 1;
for(; p && !ch[p][x]; p = fa[p]) ch[p][x] = np;
if(!p) fa[np] = 1;
else{
int q = ch[p][x];
if(len[q] == len[p] + 1) fa[np] = q;
else {
int nq = ++tot;
memcpy(ch[nq], ch[q], sizeof(ch[nq]));
fa[nq] = fa[q], fa[np] = fa[q] = nq, len[nq] = len[p] + 1;
for(; ch[p][x] == q; p = fa[p]) ch[p][x] = nq;
}
}
}
}sam;
vector<int> g[N];
void dfs1(int u){
for(auto v : g[u]){
dfs1(v);
siz[u] += siz[v];
}
dp[u] = siz[u];
}
bool vis[N];
int dfs2(int u){
if(vis[u]) return dp[u];
vis[u] = true;
for(int i = 0; i < 26; i++){
int v = sam.ch[u][i];
if(v) dp[u] += dfs2(v);
}
return dp[u];
}
void build(int t){
for(int i = 1; i <= sam.tot; i++){
if(sam.fa[i]) g[sam.fa[i]].emplace_back(i);
}
if(!t){
for(int i = 1; i <= sam.tot; i++) dp[i] = siz[i] = 1;
} else {
dfs1(1);
}
dp[1] = siz[1] = 0;
dfs2(1);
}
void query(int u, int k){
if(k > dp[u]){
cout << -1;
return;
}
if(k <= siz[u]) return;
k -= siz[u];
for(int i = 0; i < 26; i++){
int v = sam.ch[u][i];
if(k > dp[v]) k -= dp[v];
else{
cout << (char)('a' + i);
query(v, k);
return;
}
}
}
inline void solve(){
string s; cin >> s;
for(int i = 0; i < s.size(); i++) sam.extend(s[i] - 'a');
int t, k; cin >> t >> k;
build(t);
query(1, k);
}
signed main(){
//ios_base::sync_with_stdio(false), cin.tie(0);
cout << fixed << setprecision(12);
int t = 1; //cin >> t;
while(t--) solve();
return 0;
}
边栏推荐
- 【无标题】
- 【微信小程序】小程序突破小程序二维码数量限制
- “由于找不到MSVCP140.dll,无法继续执行代码,重新安装程序可能会解决此问题等”解决方案
- 2022.7.30
- Navicat connection MySQL error: 1045 - Access denied for user 'root'@'localhost' (using password YES)
- PhpMetrics 使用
- vulnhub靶机AI-Web-1.0渗透笔记
- 【导航规划】导航规划背景知识总结
- Learning about XML (1)
- The Road to Ad Monetization for Uni-app Mini Program Apps: Rewarded Video Ads
猜你喜欢

通过社交媒体建立个人IP的 5 种行之有效的策略

cnpm安装步骤

MySQL 8.0.29 设置和修改默认密码

Py's pdpbox: a detailed introduction to pdpbox, installation, and case application

可视化工具Netron介绍

ClickHouse to create a database to create a table view dictionary SQL

Go1.18升级功能 - 模糊测试Fuzz 从零开始Go语言

详解操作符

cnpm installation steps

MySQL 8.0.29 decompressed version installation tutorial (valid for personal testing)
随机推荐
MySql 5.7.38 download and installation tutorial, and realize the operation of MySql in Navicat
阿里云视频点播+项目实战
MYSQL JDBC Book Management System
Golang 切片删除指定元素的几种方法
【Untitled】
MySql 5.7.38下载安装教程 ,并实现在Navicat操作MySql
mysql获取近7天,7周,7月,7年日期,根据当前时间获取近7天,7周,7月,7年日期
IDEA使用技巧
2022.7.28
Day016 类和对象
MySQL压缩包方式安装,傻瓜式教学
VS2017编译Tars测试工程
只会纯硬件,让我有点慌
正则表达式语法及使用
【高等数学】矩阵与向量组的秩和等价
Solve npm warn config global `--global`, `--local` are deprecated. use `--location=global` instead
ML之shap:基于FIFA 2018 Statistics(2018年俄罗斯世界杯足球赛)球队比赛之星分类预测数据集利用RF随机森林+计算SHAP值单样本力图/依赖关系贡献图可视化实现可解释性之攻略
MYSQL JDBC图书管理系统
cmd (command line) to operate or connect to the mysql database, and to create databases and tables
【Untitled】