当前位置:网站首页>[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;
}
边栏推荐
- Successfully solved ImportError: always import the name '_validate_lengths'
- ZZULIOJ:1119: 数列有序
- for...in 和 for...of 的区别
- 一文详解:SRv6 Policy模型、算路及引流
- MySQL进阶sql性能分析
- Apache Doris系列之:深入认识实时分析型数据库Apache Doris
- Learning about XML (1)
- IDEA2021.2安装与配置(持续更新)
- 成功解决ModuleNotFoundError: No module named ‘Image‘
- Successfully resolved ModuleNotFoundError: No module named 'Image'
猜你喜欢
![[MySQL] DQL related operations](/img/a5/c92e0404c6a970a62595bc7a3b68cd.gif)
[MySQL] DQL related operations

IDEA 连接 数据库

Detailed explanation of the delete problem of ClickHouse delete data
![[MySQL] Related operations on databases and tables in MySQL](/img/a5/c92e0404c6a970a62595bc7a3b68cd.gif)
[MySQL] Related operations on databases and tables in MySQL

抽象类和接口(学习笔记)

MySql 5.7.38 download and installation tutorial, and realize the operation of MySql in Navicat

【MySQL】Mysql事务以及权限管理

Abstract classes and interfaces (study notes)

A detailed explanation: SRv6 Policy model, calculation and drainage

Chapter 8 Intermediate Shell Tools II
随机推荐
【MySQL】MySQL中对数据库及表的相关操作
IDEA2021.2安装与配置(持续更新)
MySQL连接时出现2003错误
【Untitled】
@RequestBody、 @RequestParam 、 @PathVariable 和 @Vaild 注解
宁波中宁典当转让29.5%股权为283.38万元,2021年所有者权益为968.75万元
【科研】文献下载神器方式汇总
MySQL联合查询(多表查询)
DFS题单以及模板汇总
tcp协议传输中的粘包问题
ZZULIOJ:1120: 最值交换
2022.7.28
The most powerful and most commonly used SQL statements in history
The Road to Ad Monetization for Uni-app Mini Program Apps: Rewarded Video Ads
【2022-05-31】JS逆向之易企秀
编码与进制
grub learning
MySQL 8.0.29 decompressed version installation tutorial (valid for personal testing)
PS基础学习(一)
cnpm的安装与使用