[LOJ3049] [十二省联考 2019] 字符串问题
题目链接
LOJ:https://loj.ac/problem/3049
洛谷:https://www.luogu.org/problemnew/show/P5284
BZOJ:https://www.lydsy.com/JudgeOnline/problem.php?id=5496
Solution
小清新字符串题
不过小样例是真的强,窝调了一小时样例然后1A了
思路还是很清晰的,首先可以得到一个\(O(n^3)\)的暴力,我们直接大力枚举然后匹配连边,然后\(\rm toposort\)求最长连就好了,注意有环就无解。
然后我们大力优化这个暴力就好了,我们用后缀树优化建边,每个子串倍增定位,然后对应到后缀树的点上就好了。
但是这样是不对的,对于\(a\geqslant b\)的情况这样是没有问题的,否则一个点可能有很多\(a,b\),那么长度大的\(b\)不能连向\(a\)。
所以有两种思路,一是类似虚树的把所有需要用的点都建出来,二是每个点开个\(\rm vector\)然后把子串挂在\(\rm vector\)上,然后\(\rm sort\)之后连边就好了。
复杂度都是\(O(n\log n)\),下面代码写的是第二种。
#include<bits/stdc++.h>
using namespace std;
void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
#define ll long long
void print(ll x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(ll x) {if(!x) putchar('0');else print(x);putchar('\n');}
#define lf double
#define pii pair<int,int >
#define vec vector<int >
#define pb push_back
#define mp make_pair
#define fr first
#define sc second
const int maxn = 8e5+10;
const int inf = 1e9;
const lf eps = 1e-8;
ll dis[maxn];
char s[maxn];
vector<int > t[maxn];
int par[maxn],ml[maxn],tr[maxn][26],lstp=1,stot=1,fa[maxn][20];
int pos[maxn],na,nb,posa[maxn],posb[maxn],len[maxn],is[maxn],lst[maxn],d[maxn];
int head[maxn],tot;
struct edge{int to,nxt;}e[maxn<<1];
void add(int u,int v) {e[++tot]=(edge){v,head[u]},head[u]=tot,d[v]++;}
int append(int x) {
int p=lstp,np=++stot;lstp=np,ml[np]=ml[p]+1;
for(;p&&tr[p][x]==0;p=par[p]) tr[p][x]=np;
if(!p) return par[np]=1,np;
int q=tr[p][x];
if(ml[q]>ml[p]+1) {
int nq=++stot;ml[nq]=ml[p]+1;
memcpy(tr[nq],tr[q],sizeof tr[nq]);
par[nq]=par[q],par[q]=par[np]=nq;
for(;p&&tr[p][x]==q;p=par[p]) tr[p][x]=nq;
} else par[np]=q;
return np;
}
int cmp(int x,int y) {return len[x]==len[y]?is[x]<is[y]:len[x]<len[y];}
void build() {
scanf("%s",s+1);
for(int n=strlen(s+1),i=n;i;i--) pos[i]=append(s[i]-'a');
for(int i=2;i<=stot;i++) fa[i][0]=par[i];
for(int i=1;i<=18;i++)
for(int j=2;j<=stot;j++)
fa[j][i]=fa[fa[j][i-1]][i-1];
read(na);
for(int i=1;i<=na;i++) {
int l,r;read(l),read(r);
int now=pos[l];
for(int j=18;~j;j--) if(ml[fa[now][j]]>=r-l+1) now=fa[now][j];
t[now].push_back(posa[i]=++stot);
len[stot]=r-l+1,is[stot]=1;
}read(nb);
for(int i=1;i<=nb;i++) {
int l,r;read(l),read(r);
int now=pos[l];
for(int j=18;~j;j--) if(ml[fa[now][j]]>=r-l+1) now=fa[now][j];
t[now].push_back(posb[i]=++stot);
len[stot]=r-l+1;
}
for(int x=1;x<=stot;x++) {
int pre=x,L=t[x].size();sort(t[x].begin(),t[x].end(),cmp);
for(int v,i=0;i<L;i++) {
v=t[x][i];add(pre,v);
if(!is[v]) pre=v,len[v]=0;
}lst[x]=pre;
}
for(int x=2;x<=stot;x++) if(par[x]) add(lst[par[x]],x);
int q;read(q);for(int i=1,x,y;i<=q;i++) read(x),read(y),add(posa[x],posb[y]);
}
void solve() {
queue<int > q;ll cnt=0,ans=0;while(!q.empty()) q.pop();
for(int i=1;i<=stot;i++) if(!d[i]) q.push(i);
while(!q.empty()) {
int x=q.front();q.pop();cnt++;
for(int v,i=head[x];i;i=e[i].nxt) {
v=e[i].to;dis[v]=max(dis[v],dis[x]+len[v]);
if(!(--d[v])) q.push(v);ans=max(ans,dis[v]);
}
}write(cnt==stot?ans:-1ll);
}
void clear() {
for(int i=1;i<=stot;i++) {
memset(tr[i],0,sizeof tr[i]);
memset(fa[i],0,sizeof fa[i]);
par[i]=ml[i]=len[i]=dis[i]=d[i]=lst[i]=pos[i]=is[i]=head[i]=0;
t[i].clear();
}tot=0;stot=lstp=1;
}
int main() {
int T;read(T);while(T--) build(),solve(),clear();
return 0;
}
[LOJ3049] [十二省联考 2019] 字符串问题的更多相关文章
- LOJ3049 [十二省联考2019] 字符串问题 【后缀自动机】【倍增】【拓扑排序】
题目分析: 建出后缀自动机,然后把A串用倍增定位到后缀自动机上,再把B串用倍增定位到后缀自动机上. SAM上每个点上的A串根据长度从小到大排序,建点,依次连边. 再对于SAM上面每个点,连到儿子的边, ...
- [十二省联考2019]字符串问题——后缀自动机+parent树优化建图+拓扑序DP+倍增
题目链接: [十二省联考2019]字符串问题 首先考虑最暴力的做法就是对于每个$B$串存一下它是哪些$A$串的前缀,然后按每组支配关系连边,做一遍拓扑序DP即可. 但即使忽略判断前缀的时间,光是连边的 ...
- 【BZOJ5496】[十二省联考2019]字符串问题(后缀树)
[BZOJ5496][十二省联考2019]字符串问题(后缀树) 题面 BZOJ 洛谷 题解 首先显然可以把具有支配关系的串从\(A\)到\(B\)连一条有向边,如果\(B_i\)是\(A_j\)的前缀 ...
- P5284 [十二省联考2019]字符串问题
这是一道涵盖了字符串.图论.数据结构三个方面的综合大题. 把这道题放在D1T2的人应该拖出去打 前置芝士 首先,您至少要会topsort. 其次,如果您只想拿个暴力分,字符串Hash就足够了:如果您想 ...
- Luogu P5284 [十二省联考2019]字符串问题
好难写的字符串+数据结构问题,写+调了一下午的说 首先理解题意后我们对问题进行转化,对于每个字符串我们用一个点来代表它们,其中\(A\)类串的点权为它们的长度,\(B\)类串的权值为\(0\) 这样我 ...
- 洛谷P5284 [十二省联考2019]字符串问题 [后缀树]
传送门 思路 设\(dp_i\)表示以\(i\)结尾的\(A\)串,能达到的最长长度. 然后发现这显然可以\(i\)往自己控制的\(k\)连边,\(k\)往能匹配的\(j\)连边,就是个最长路,只要建 ...
- 洛谷.5284.[十二省联考2019]字符串问题(后缀自动机 拓扑 DP)
LOJ BZOJ 洛谷 对这题无话可说,确实比较...裸... 像dls说的拿拓扑和parent树一套就能出出来了... 另外表示BZOJ Rank1 tql... 暴力的话,由每个\(A_i\)向它 ...
- 【题解】Luogu P5284 [十二省联考2019]字符串问题
原题传送门 我用sa做的本题 (码量似乎有点大) 先对原串建sa 考虑如何建图: 从大到小枚举长度len 先将height中等于len的两个位置在并查集合并起来,将lst也合并(lst是链表) 再将长 ...
- Luogu5289 十二省联考2019字符串问题(后缀数组+拓扑排序+线段树/主席树/KDTree)
先考虑80分做法,即满足A串长度均不小于B串,容易发现每个B串对应的所有A串在后缀数组上都是一段连续区间,线段树优化连边然后判环求最长链即可.场上就写了这个. 100分也没有什么本质区别,没有A串长度 ...
随机推荐
- Revit开发小技巧——撤销操作
最近开发Revit命令需要限制某些操作,思路是监控用户操作,如果达到限制条件,将操作回退.思路有两种: 1.调用WindowsAPI,发送快捷命令Ctrl+Z. 2.通过Revit底层提供DLL找到回 ...
- 《杜增强讲Unity之Tanks坦克大战》7-坦克血条
7 坦克血条 点击菜单GameObject->UI->Slider创建Slider 选中EventSystem,设置Horizontal Axis为HorzontalUI,Vertic ...
- gitlab+jenkins持续集成--http方式连接gitlab
http://v.youku.com/v_show/id_XMjk3NTYyMDUxMg==.html?spm=a2h3j.8428770.3416059.1
- 15 Puzzle (4乘4谜题) IDA*(DFS策略与曼哈顿距离启发) 的C语言实现
大家好!这是我的第一篇博客,由于之前没有撰写博客的经验,并且也是初入计算机和人工智能领域,可能有些表述或者理解不当,还请大家多多指教. 一.撰写目的 由于这个学期在上算法与数据结构课程的时候,其中一个 ...
- 使用spring整合Quartz实现—定时器
使用spring整合Quartz实现—定时器(Maven项目做演示) 不基于特定的基类的方法 一,开发环境以及依赖的jar包 Spring 4.2.6.RELEASE Maven 3.3.9 Jdk ...
- plsql 不修改tnsnames.ora文件
PLSQL 不修改tnsname直接连数据库的方式在PLSQL的Database中直接输入192.168.1.6:1521/VP.其中192.168.1.6为数据库的IP:1521为数据库端口:VP为 ...
- 互评Beta版本——Thunder组爱阅app(探路者团队测评)
基于NABCD评论作品,及改进建议 每个小组评论其他小组beta发布的作品. 1.根据(不限于)NABCD评论作品的选题; N(Need,需求):在Beta中加入了书友QQ群,以及反馈建议,更好的 ...
- PSP Daily新增功能说明书
1.选择输入类别时可以记录原来的输入,支持用户选择记录清空功能 2.添加“恢复最近”button,点击这个按钮可以跳出一个页面显示最近的excel记录,用户可以通过勾选相应的excel文件名,恢复选中 ...
- Bing词典vs有道词典比对测试报告——功能篇之辅助功能,差异化功能及软件的效能
1.辅助功能: 和有道相比,必应的词典加入了换肤功能,用户可以选择喜欢的颜色,而且必应的皮肤也比较多,这一点设计给必应增色不少. 相对而言,有道则加入了调节客户端字体的大小,如下,也比较人性化 2.差 ...
- iOS开发学习-cocoapods的配置安装
安装coacoapods步骤: 在终端输入如下命令,升级ruby版本: sudo gem update —system 出现这个,标志着安装成功. 完成之后,再输入如下命令: gem sources ...