当前位置:网站首页>[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;
}
边栏推荐
- Go语学习笔记 - gorm使用 - 表增删改查 Web框架Gin(八)
- Difference between cookie and session
- Go1.18升级功能 - 模糊测试Fuzz 从零开始Go语言
- mysql跨库关联查询(dblink)
- 【Untitled】
- Solve npm warn config global `--global`, `--local` are deprecated. use `--location=global` instead
- Detailed explanation of the delete problem of ClickHouse delete data
- IJCAI2022 Tutorial | Spoken Language Comprehension: Recent Advances and New Fields
- PhpMetrics usage
- Abstract classes and interfaces (study notes)
猜你喜欢
PyTorch模型导出到ONNX文件示例(LeNet-5)
详解操作符
Go语学习笔记 - gorm使用 - gorm处理错误 Web框架Gin(十)
连号区间数
PhpMetrics 使用
Apache Doris系列之:安装与部署详细步骤
Gxlcms audio novel system/novel listening system source code
Apache Doris系列之:深入认识实时分析型数据库Apache Doris
通过对抗性知识蒸馏压缩深度图神经网络
ML's shap: Based on FIFA 2018 Statistics (2018 Russia World Cup) team match star classification prediction data set using RF random forest + calculating SHAP value single-sample force map/dependency c
随机推荐
ThinkPHP high imitation blue play cloud network disk system source code / docking easy payment system program
【Untitled】
Go1.18升级功能 - 泛型 从零开始Go语言
Rust编译报错:error: linker `cc` not found
MySQL 8.0.29 set and modify the default password
二进制序列
d违反常了吗
成功解决ImportError: cannot import name ‘_validate_lengths‘
IJCAI2022 Tutorial | Spoken Language Comprehension: Recent Advances and New Fields
连号区间数
【MySQL】Mysql事务以及权限管理
2sk2225代换3A/1500V中文资料【PDF数据手册】
Alibaba Cloud video on demand + project combat
go版本升级
反转链表-头插反转法
【MySQL】MySQL中对数据库及表的相关操作
力扣题(3)—— 无重复字符的最长子串
MySQL cursors
【无标题】
Navicat connection MySQL error: 1045 - Access denied for user 'root'@'localhost' (using password YES)