洛谷P5284 [十二省联考2019]字符串问题 [后缀树]
思路
设\(dp_i\)表示以\(i\)结尾的\(A\)串,能达到的最长长度。
然后发现这显然可以\(i\)往自己控制的\(k\)连边,\(k\)往能匹配的\(j\)连边,就是个最长路,只要建出图来就完事了。
显然可以用数据结构得到两点之间是否有边,于是就获得了40分的好成绩。
考虑优化这个建图,字符串也就那么几个数据结构,那就后缀树吧。
有了后缀树,可以发现\(k\)会向\(k\)所在的节点的子树连边,注意不包括\(k\)自己的节点。
那么自己节点怎么办呢?把在这里的所有串拆开然后按长度排一下序即可。
然后就是用虚点优化,随便搞就好了。
这省选题好像也不难
代码先咕着,下午再写。
uptade:下午由于数组开小狂WA,怒调3小时无果,还因为size(),lower_bound()等函数炸掉而一脸懵逼……
数组就应该能开多大开多大……
代码
#include<bits/stdc++.h>
clock_t t=clock();
namespace my_std{
using namespace std;
#define pii pair<int,int>
#define fir first
#define sec second
#define MP make_pair
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define drep(i,x,y) for (int i=(x);i>=(y);i--)
#define go(x) for (int i=head[x];i;i=edge[i].nxt)
#define templ template<typename T>
#define sz 1204040
typedef long long ll;
typedef double db;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
templ inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);}
templ inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
templ inline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
templ inline void read(T& t)
{
t=0;char f=0,ch=getchar();double d=0.1;
while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
if(ch=='.'){ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();}
t=(f?-t:t);
}
template<typename T,typename... Args>inline void read(T& t,Args&... args){read(t); read(args...);}
char __sr[1<<21],__z[20];int __C=-1,__zz=0;
inline void Ot(){fwrite(__sr,1,__C+1,stdout),__C=-1;}
inline void print(register int x)
{
if(__C>1<<20)Ot();if(x<0)__sr[++__C]='-',x=-x;
while(__z[++__zz]=x%10+48,x/=10);
while(__sr[++__C]=__z[__zz],--__zz);__sr[++__C]='\n';
}
void file()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
}
inline void chktime()
{
#ifndef ONLINE_JUDGE
cout<<(clock()-t)/1000.0<<'\n';
#endif
}
#ifdef mod
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;return ret;}
ll inv(ll x){return ksm(x,mod-2);}
#else
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x;return ret;}
#endif
// inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std;
char s[sz];
int N,n,m;
int la[sz],ra[sz],lb[sz],rb[sz];
int fa[sz],len[sz],ch[sz][27],cnt=1,lst=1;
int edp[sz];
void insert(int c)
{
int cur=++cnt,p=lst;lst=cur;
len[cur]=len[p]+1;
while (p&&!ch[p][c]) ch[p][c]=cur,p=fa[p];
if (!p) return (void)(fa[cur]=1);
int q=ch[p][c];
if (len[p]+1==len[q]) return (void)(fa[cur]=q);
int t=++cnt;
memcpy(ch[t],ch[q],sizeof(ch[q]));
len[t]=len[p]+1;fa[t]=fa[q];
while (p!=-1&&ch[p][c]==q) ch[p][c]=t,p=fa[p];
fa[q]=fa[cur]=t;
}
void calcEndPos(){int x=1;drep(i,N,1) x=ch[x][s[i]-'a'+1],edp[i]=x;}
struct hh{int t,nxt;}edge[sz];
int head[sz],ecnt;
void make_edge(int f,int t){edge[++ecnt]=(hh){t,head[f]};head[f]=ecnt;}
int Fa[sz][25];
void dfs1(int x,int fa){Fa[x][0]=fa;rep(i,1,20) Fa[x][i]=Fa[Fa[x][i-1]][i-1];go(x) dfs1(edge[i].t,x);}
vector<pii>va[sz],vb[sz];
void ins(int id,int lenth,int p)
{
drep(i,20,0) if (Fa[p][i]&&len[Fa[p][i]]>=lenth) p=Fa[p][i];
if (id<=n) va[p].push_back(MP(lenth,id));
else vb[p].push_back(MP(lenth,id));
}
int son[sz],cc;
int deg[sz];
struct hhh{int f,t,w,nxt;}E[sz];
int Head[sz],Ecnt;
void MakeEdge(int f,int t,int w){++deg[t];E[++Ecnt]=(hhh){f,t,w,Head[f]};Head[f]=Ecnt;}
int lastt=0;
void dfs2(int x)
{
sort(va[x].begin(),va[x].end());
int nxt=cc+1,las;cc+=va[x].size()+1;las=cc;
drep(i,(int)va[x].size()-1,0) MakeEdge(nxt+i,nxt+i+1,0),MakeEdge(nxt+i,va[x][i].sec,va[x][i].fir);
rep(i,0,(int)vb[x].size()-1)
{
int pos=lower_bound(va[x].begin(),va[x].end(),MP(vb[x][i].fir,-1))-va[x].begin();
MakeEdge(vb[x][i].sec,nxt+pos,0);
}
go(x) dfs2(edge[i].t),MakeEdge(las,son[edge[i].t],0);
son[x]=nxt;
}
ll dp[sz];
bool vis[sz];
void work()
{
cin>>(s+1);
N=strlen(s+1);
drep(i,N,1) insert(s[i]-'a'+1);
calcEndPos();
rep(i,2,cnt) make_edge(fa[i],i);
dfs1(1,0);
int K,x,y;
read(n);
rep(i,1,n) read(la[i],ra[i]),ins(i,ra[i]-la[i]+1,edp[la[i]]),dp[i]=ra[i]-la[i]+1;
read(m);
rep(i,1,m) read(lb[i],rb[i]),ins(i+n,rb[i]-lb[i]+1,edp[lb[i]]);
read(K);
while (K--) read(x,y),MakeEdge(x,y+n,0);
cc=n+m;
dfs2(1);
queue<int>q;
ll ans=0;
rep(i,1,cc) if (!deg[i]) q.push(i);
while (!q.empty())
{
int x=q.front();q.pop();vis[x]=1;
chkmax(ans,dp[x]);
for (int i=Head[x];i;i=E[i].nxt)
{
int v=E[i].t;--deg[v];chkmax(dp[v],dp[x]+E[i].w);
if (!deg[v]) q.push(v);
}
}
bool flg=1;
rep(i,1,cc) flg&=vis[i];
printf("%lld\n",flg?ans:-1ll);
rep(i,1,N) s[i]='\0',edp[i]=0;
rep(i,1,n) la[i]=ra[i]=0;
rep(i,1,m) lb[i]=rb[i]=0;
rep(i,1,cnt) { fa[i]=len[i]=head[i]=0; rep(j,1,26) ch[i][j]=0; }
rep(i,1,cc) Head[i]=0,va[i].clear(),vb[i].clear(),son[i]=0,deg[i]=0,dp[i]=0,vis[i]=0;
ecnt=cc=Ecnt=0;cnt=lst=1;
}
int main()
{
file();
int T;read(T);
while (T--) work();
return 0;
}
洛谷P5284 [十二省联考2019]字符串问题 [后缀树]的更多相关文章
- 洛谷.5284.[十二省联考2019]字符串问题(后缀自动机 拓扑 DP)
LOJ BZOJ 洛谷 对这题无话可说,确实比较...裸... 像dls说的拿拓扑和parent树一套就能出出来了... 另外表示BZOJ Rank1 tql... 暴力的话,由每个\(A_i\)向它 ...
- 洛谷P5284 [十二省联考2019]字符串问题(SAM+倍增+最长路)
题面 传送门 题解 首先,我们把串反过来,那么前缀就变成后缀,建一个\(SAM\).我们发现一个节点的后缀是它的所有祖先 那么我们是不是直接按着\(parent\)树建边就可以了呢? 显然不是.我们假 ...
- [十二省联考2019]字符串问题——后缀自动机+parent树优化建图+拓扑序DP+倍增
题目链接: [十二省联考2019]字符串问题 首先考虑最暴力的做法就是对于每个$B$串存一下它是哪些$A$串的前缀,然后按每组支配关系连边,做一遍拓扑序DP即可. 但即使忽略判断前缀的时间,光是连边的 ...
- 洛谷.5283.[十二省联考2019]异或粽子(可持久化Trie 堆)
LOJ 洛谷 考场上都拍上了,8:50才发现我读错了题=-= 两天都读错题...醉惹... \(Solution1\) 先求一遍前缀异或和. 假设左端点是\(i\),那么我们要在\([i,n]\)中找 ...
- 洛谷P5289 [十二省联考2019]皮配(01背包)
啊啊啊边界判错了搞死我了QAQ 这题是一个想起来很休闲写起来很恶心的背包 对于\(k=0\)的情况,可以发现选阵营和选派系是独立的,对选城市选阵营和学校选派系分别跑一遍01背包就行了 对于\(k> ...
- 洛谷 5291 [十二省联考2019]希望(52分)——思路+树形DP
题目:https://www.luogu.org/problemnew/show/P5291 考场上写了 16 分的.不过只得了 4 分. 对于一个救援范围,其中合法的点集也是一个连通块. 2n 枚举 ...
- P5284 [十二省联考2019]字符串问题
这是一道涵盖了字符串.图论.数据结构三个方面的综合大题. 把这道题放在D1T2的人应该拖出去打 前置芝士 首先,您至少要会topsort. 其次,如果您只想拿个暴力分,字符串Hash就足够了:如果您想 ...
- Luogu P5284 [十二省联考2019]字符串问题
好难写的字符串+数据结构问题,写+调了一下午的说 首先理解题意后我们对问题进行转化,对于每个字符串我们用一个点来代表它们,其中\(A\)类串的点权为它们的长度,\(B\)类串的权值为\(0\) 这样我 ...
- 【题解】Luogu P5284 [十二省联考2019]字符串问题
原题传送门 我用sa做的本题 (码量似乎有点大) 先对原串建sa 考虑如何建图: 从大到小枚举长度len 先将height中等于len的两个位置在并查集合并起来,将lst也合并(lst是链表) 再将长 ...
随机推荐
- spring整合quartz异常:org.quartz.JobPersistenceException: Couldn't clean volatile data: Unknown column 'IS_VOLATILE' in 'where clause'
自己的SSM项目中要用到定时器,初期使用Timer,后来用spring 的schedule,都比较简单,所以功能比较单一.后来就研究quartz,准备整合到项目中.遇到了异常,异常内容如下: [201 ...
- bugku web 管理员系统
页面是一个登陆表单,需要账号密码,首先f12查看源代码,发现有一段可疑的注释,明显是base64,解码得到test123,似乎是一个类似于密码的东西,既然是管理员,就猜测用户名是admin,填上去试一 ...
- linux搭建所遇到的坑elasticsearch-6.3.0
注意: 不能使用主账号(root账号运行,必须使用子账号登录) 第一步安装:: wget https://artifacts.elastic.co/downloads/elasticsearch/el ...
- Educational Codeforces Round 62 Div. 2
突然发现上一场edu忘记写了( A:签到. #include<iostream> #include<cstdio> #include<cmath> #include ...
- leanote使用本地账户时,去掉待同步的小红点
切换开发者工具,如下图,点击左上角的箭头图标,选取元素,直接选择小红点. 然后会看到小红点来自于resources/app/public/themes/default.css文件中2092行: .it ...
- emwin之创建窗口与窗口回调函数的句柄是一致的
@2019-04-28 [小记] 由函数GUI_CreateDialogBox 创建的窗口所返回的句柄与回调函数形参中的窗口句柄参数是一样的
- Java 8 特性 —— lambda 表达式
Lambda 表达式 Lambda表达式本质上是一个匿名方法.常见的一个例子是,在 IDEA + JDK8 的环境下按照Java传统的语法规则编写一个线程: new Thread(new Runnab ...
- 互相关(cross-correlation)及其在Python中的实现
互相关(cross-correlation)及其在Python中的实现 在这里我想探讨一下“互相关”中的一些概念.正如卷积有线性卷积(linear convolution)和循环卷积(circular ...
- C/C++面试题:编写类String的构造函数、析构函数和赋值函数。
转https://www.cnblogs.com/alinh/p/9636500.html 考点:构造函数.析构函数和赋值函数的编写方法出现频率:☆☆☆☆☆已知类String的原型为: ...
- JGUI源码:实现蒙版层显示(18)
有的时候需要显示一个蒙版层,蒙版层显示的主要原理是在指定元素比如div上创建一个子元素div,设置absolute.宽高100%.设置z-index置于顶层,设置半透明效果,fadein,fadeou ...