传送门


思路

设\(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]字符串问题 [后缀树]的更多相关文章

  1. 洛谷.5284.[十二省联考2019]字符串问题(后缀自动机 拓扑 DP)

    LOJ BZOJ 洛谷 对这题无话可说,确实比较...裸... 像dls说的拿拓扑和parent树一套就能出出来了... 另外表示BZOJ Rank1 tql... 暴力的话,由每个\(A_i\)向它 ...

  2. 洛谷P5284 [十二省联考2019]字符串问题(SAM+倍增+最长路)

    题面 传送门 题解 首先,我们把串反过来,那么前缀就变成后缀,建一个\(SAM\).我们发现一个节点的后缀是它的所有祖先 那么我们是不是直接按着\(parent\)树建边就可以了呢? 显然不是.我们假 ...

  3. [十二省联考2019]字符串问题——后缀自动机+parent树优化建图+拓扑序DP+倍增

    题目链接: [十二省联考2019]字符串问题 首先考虑最暴力的做法就是对于每个$B$串存一下它是哪些$A$串的前缀,然后按每组支配关系连边,做一遍拓扑序DP即可. 但即使忽略判断前缀的时间,光是连边的 ...

  4. 洛谷.5283.[十二省联考2019]异或粽子(可持久化Trie 堆)

    LOJ 洛谷 考场上都拍上了,8:50才发现我读错了题=-= 两天都读错题...醉惹... \(Solution1\) 先求一遍前缀异或和. 假设左端点是\(i\),那么我们要在\([i,n]\)中找 ...

  5. 洛谷P5289 [十二省联考2019]皮配(01背包)

    啊啊啊边界判错了搞死我了QAQ 这题是一个想起来很休闲写起来很恶心的背包 对于\(k=0\)的情况,可以发现选阵营和选派系是独立的,对选城市选阵营和学校选派系分别跑一遍01背包就行了 对于\(k> ...

  6. 洛谷 5291 [十二省联考2019]希望(52分)——思路+树形DP

    题目:https://www.luogu.org/problemnew/show/P5291 考场上写了 16 分的.不过只得了 4 分. 对于一个救援范围,其中合法的点集也是一个连通块. 2n 枚举 ...

  7. P5284 [十二省联考2019]字符串问题

    这是一道涵盖了字符串.图论.数据结构三个方面的综合大题. 把这道题放在D1T2的人应该拖出去打 前置芝士 首先,您至少要会topsort. 其次,如果您只想拿个暴力分,字符串Hash就足够了:如果您想 ...

  8. Luogu P5284 [十二省联考2019]字符串问题

    好难写的字符串+数据结构问题,写+调了一下午的说 首先理解题意后我们对问题进行转化,对于每个字符串我们用一个点来代表它们,其中\(A\)类串的点权为它们的长度,\(B\)类串的权值为\(0\) 这样我 ...

  9. 【题解】Luogu P5284 [十二省联考2019]字符串问题

    原题传送门 我用sa做的本题 (码量似乎有点大) 先对原串建sa 考虑如何建图: 从大到小枚举长度len 先将height中等于len的两个位置在并查集合并起来,将lst也合并(lst是链表) 再将长 ...

随机推荐

  1. linux cp 直接覆盖不提示信息 解决方法

    默认情况下,cp覆盖时,无论加什么参数 -f 之类的 还是提示是否覆盖. 原因是:服务器会默认增加别名 alias cp=’cp -i’,当你执行cp时,其实执行的是cp –i. [root@ltt0 ...

  2. 为App添加Log日志文件

    using System; using System.Globalization; using System.IO; using System.Text; using System.Windows.F ...

  3. python 迭代器、生成器、枚举的使用

    迭代器 器:包含了多个值的容器 迭代:循环反馈(一次从容器中取出一个值) 迭代器:从装有多个值的容器中一次取出一个值给外界 遍历:被遍历的对象必须是有序容器 ls = [1, 2, 3, 4, 5] ...

  4. Oracle 给予访问其他用户包的权限

    grant execute on apps.SPM_CON_INVOICE_INF_PKG to diq; grant  DEBUG on apps.SPM_CON_INVOICE_INF_PKG t ...

  5. [BZOJ4318] OSU!

    比较简单,每个键分两种情况计算期望. 然而要注意的是,期望是线性运算,期望的平方不是平方的期望 . #include <cmath> #include <queue> #inc ...

  6. Prometheus-Consul-Api

    官方地址:https://www.consul.io/docs/agent/http.html consul的主要接口是RESTful HTTP API,该API可以用来增删查改nodes.servi ...

  7. Jmeter 逻辑控制器总结

    本文主要总结Jmeter的逻辑控制器: 逻辑控制器下一共16个控制器: 1.foreach controller循环控制器 定义变量数组,按数组遍历循环   2.simple controller 简 ...

  8. js根据毫米/厘米算像素px

    <html><meta http-equiv="content-type" content="text/html;charset=utf-8" ...

  9. 适用于单片机的数据加密算法:xxtea

    转:https://www.cnblogs.com/LittleTiger/p/4384741.html 各位大侠在做数据传输时,有没有考虑过把数据加密起来进行传输,若在串口或者无线中把所要传的数据加 ...

  10. 12、Filter(拦截器)

    一.过滤器(Filter):又称拦截器.实现Filter接口的类我们称之为Filter(过滤器或拦截器),Filter可以对用户访问的资源进行拦截.例如:客户端发送请求是,先将请求拦截下来,判断用户是 ...