Codeforces 1536B Prinzessin der Verurteilung 题解 [ 紫 ] [ 后缀自动机 ] [ 动态规划 ] [ 拓扑排序 ]
Prinzessin der Verurteilung:最短未出现字符串的板子。
思路
考虑在 SAM 上 dp,定义 \(dp_i\) 表示从 \(i\) 节点走到 NULL 节点所花费的最少步数。显然我们建出反图,跑 DAG 上 dp 即可。转移如下:
\]
输出方案的话记录下每个 dp 值的先驱,最后从 \(1\) 号节点开始遍历一遍即可。
注意,如果某个节点某个字母的转移边不存在的话,也需要建边,可以用一个超级源点 \(0\) 把这些 SAM 上不存在的边记录下来,这样才能算出不在里面出现过的字符串。
时间复杂度 \(O(tn|\sum|)\),应该是最优复杂度了。
代码
#include <bits/stdc++.h>
#define fi first
#define se second
#define lc (p<<1)
#define rc ((p<<1)|1)
#define eb(x) emplace_back(x)
#define pb(x) push_back(x)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using pi=pair<int,int>;
int n,len[2005],fa[2005],ch[2005][26],tot=1,np=1,rd[2005];
char s[1005];
vector<pi>g[2005];
struct node{
int v=0x3f3f3f3f,frm=-1,cx=-1;
}dp[2005];
void init()
{
for(int i=0;i<=tot;i++)
{
len[i]=fa[i]=0;
for(int j=0;j<26;j++)ch[i][j]=0;
dp[i]={0x3f3f3f3f,-1,-1};
rd[i]=0;
g[i].clear();
}
tot=np=1;
}
void extend(int c)
{
int p=np;
np=++tot;
len[np]=len[p]+1;
for(;p&&ch[p][c]==0;p=fa[p])ch[p][c]=np;
if(p==0)fa[np]=1;
else
{
int q=ch[p][c];
if(len[q]==len[p]+1)fa[np]=q;
else
{
int nq=++tot;
len[nq]=len[p]+1;
fa[nq]=fa[q],fa[q]=nq,fa[np]=nq;
for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=nq;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
}
}
}
void outp()
{
int p=1;
while(p!=-1)
{
int v=dp[p].frm,c=dp[p].cx;
if(c<0)break;
cout<<char(c+'a');
p=v;
}
cout<<'\n';
}
void solve()
{
cin>>n>>s+1;
init();
for(int i=1;i<=n;i++)extend(s[i]-'a');
for(int i=1;i<=tot;i++)
{
for(int j=0;j<26;j++)
{
int v=ch[i][j];
g[v].push_back({i,j});
rd[i]++;
}
}
queue<int>q;
for(int i=0;i<=tot;i++)
{
if(rd[i]==0)
{
dp[i]={1,-1,-1};
q.push(i);
}
}
while(!q.empty())
{
int u=q.front();
q.pop();
for(auto ed:g[u])
{
int v=ed.fi,c=ed.se;
rd[v]--;
if(rd[v]==0)q.push(v);
int dpv=dp[u].v+1;
if(dpv<dp[v].v)
{
dp[v].v=dpv;
dp[v].frm=u;
dp[v].cx=c;
}
else if(dpv==dp[v].v&&dp[v].cx>c)
{
dp[v].frm=u;
dp[v].cx=c;
}
}
}
outp();
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--)solve();
return 0;
}
Codeforces 1536B Prinzessin der Verurteilung 题解 [ 紫 ] [ 后缀自动机 ] [ 动态规划 ] [ 拓扑排序 ]的更多相关文章
- 「2017 山东一轮集训 Day5」字符串 (后缀自动机, 拓扑排序)
/** 首先通过SAM求出每个串本质不同的子串 然后发现转移不好处理整体的本质不同 形如串A可能状态有a,b,ab,空,串B可能状态有b,空两种, 那么我们需要处理ab + 空 和 a + b的情况 ...
- Codeforces Round #285 (Div. 2)C. Misha and Forest(拓扑排序)
传送门 Description Let's define a forest as a non-directed acyclic graph (also without loops and parall ...
- 2021.07.17 题解 CF1385E Directing Edges(拓扑排序)
2021.07.17 题解 CF1385E Directing Edges(拓扑排序) CF1385E Directing Edges - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) ...
- 洛谷 P4248 / loj 2377 [AHOI2013] 差异 题解【后缀自动机】【树形DP】
可能是一个 SAM 常用技巧?感觉 SAM 的基础题好多啊.. 题目描述 给定一个长度为 \(n\) 的字符串 \(S\) ,令 \(T_i\) 表示它从第 \(i\) 个字符开始的后缀,求: \[ ...
- 洛谷 P3975 / loj 2102 [TJOI2015] 弦论 题解【后缀自动机】【拓扑排序】
后缀自动机入门. 题目描述 为了提高智商,ZJY 开始学习弦论. 这一天,她在<String theory>中看到了这样一道问题:对于一个给定的长度为 \(n\) 的字符串,求出它的第 \ ...
- Codeforces Round #364 (Div. 1) (差一个后缀自动机)
B. Connecting Universities 大意: 给定树, 给定2*k个点, 求将2*k个点两两匹配, 每个匹配的贡献为两点的距离, 求贡献最大值 单独考虑每条边$(u,v)$的贡献即可, ...
- codeforces 204E. Little Elephant and Strings(广义后缀自动机,Parent树)
传送门在这里. 大意: 给一堆字符串,询问每个字符串有多少子串在所有字符串中出现K次以上. 解题思路: 这种子串问题一定要见后缀自动机Parent树Dfs序统计出现次数都是套路了吧. 这道题统计子串个 ...
- [codeforces 894 E] Ralph and Mushrooms 解题报告 (SCC+拓扑排序+DP)
题目链接:http://codeforces.com/problemset/problem/894/E 题目大意: $n$个点$m$条边的有向图,每条边有一个权值,可以重复走. 第$i$次走过某条边权 ...
- Codeforces Round #541 (Div. 2) D(并查集+拓扑排序) F (并查集)
D. Gourmet choice 链接:http://codeforces.com/contest/1131/problem/D 思路: = 的情况我们用并查集把他们扔到一个集合,然后根据 > ...
- Codeforces Round #285 (Div. 2) A B C 模拟 stl 拓扑排序
A. Contest time limit per test 1 second memory limit per test 256 megabytes input standard input out ...
随机推荐
- RabbitMQ的四种交换机类型
前言 这是相关技能的详解系列,是将东西整理归纳总结,系列的进行记录与分享,这种方式更有完善性,更能成体系的学习一个技能,方便我们掌握他,这也是我们这种系列的目标,希望在跟着学习了解完这个系列后,就能将 ...
- 鸿蒙NEXT元服务:收藏、卡片、用户协议、隐私声明、分享链接、评分与评论
相比应用,元服务的功能藏的比较深,这里记录一下常用功能的位置. 1.收藏(添加至我的服务) 打开元服务-->右上角四个点-->添加至我的服务-->手机滑到负一屏-->点击&qu ...
- 【邮件伪造】SPF与DKIM验证原理及实战解析(上)
0x01 前言 大家好,我是VoltCary 本篇文章是系列邮件安全专题的第一篇,主要帮助大家掌握邮件安全的基础知识. 基础内容包括: SMTP协议 邮件安全验证原理与过程 SPF验证与DKIM签名验 ...
- 一个 tomcat 下部署多个项目(超细另类版)
前言:网上大佬们的都是一个webapps下面部署多个项目,咱们今天来点不一样的,另一种思路则是,多个webapps,每个webapps下面运行一个项目,不知如何本地部署的可以去看看我上一篇随笔 具体步 ...
- Qt 在线程中invokeMethod采用QueuedConnection模式,调用带指针参数槽,实际不会调用
widgetObject有操函数Test: void Test(int *v); 在线程中调用Test,会被忽略,实际不会调用. QMetaObject::invokeMethod(widgetObj ...
- CVE-2023-0461 漏洞分析与利用
PS: 文章首发于补天社区 漏洞分析 tcp_set_ulp里面会分配和设置 icsk->icsk_ulp_data,其类型为 tls_context tcp_setsockopt do_tcp ...
- ArkTs布局入门05——栅格布局(GridRow/GridCol)
1.概述 栅格布局是一种通用的辅助定位工具,对移动设备的界面设计有较好的借鉴作用.主要优势包括: 提供可循的规律:栅格布局可以为布局提供规律性的结构,解决多尺寸多设备的动态布局问题.通过将页面划分为等 ...
- 08C++选择结构(2)——教学
一.逻辑变量 教学视频 存储类似灯亮或灯灭.是男还是女等结果只有两种可能的数据时,可以使用逻辑型变量. 逻辑型变量用关键字bool定义,所以又称为布尔变量,其值只有两个false(假)和true(真) ...
- R数据分析:非劣效性研究设计的统计处理方法,原理和实例
在我们经常接触的统计模式中,我们是在寻求推翻原假设,证明差异,这种统计模型在传统的临床试验中,在各种统计推断中已经成为默认了.在传统的临床试验中通常会将一种新的治疗方法与标准治疗或安慰剂进行比较,从而 ...
- ChatGPT生成测试用例的最佳实践(四)
通常情况下还应该进行测试用例外部评审.将已完成的基于百度关键字搜索业务的功能和安全测试用例集的存放位置告知项目团队成员,需要预留出一定的时间,便于项目组研发.产品人员阅读,以免在项目团队测试用例评审会 ...