• 「十二省联考 2019」字符串问题——SAM+DAG


    题目

    【题目描述】

    Yazid 和 Tiffany 喜欢字符串问题。在这里,我们将给你介绍一些关于字符串的基本概念。

    对于一个字符串 $S$, 我们定义 $lvert S vert$ 表示 $S$ 的长度。

    接着,我们定义该串的子串 $Sleft( {L,R} ight)$ 表示由 $S$ 中从左往右数,第 $L$ 个字符到第 $R$ 个字符依次连接形成的字符串,特别地,如果 $L < 1$ 或 $R > lvert S vert$ 或 $L > R$,则 $Sleft( {L,R} ight)$ 表示空串。

    我们说两个字符串相等,当且仅当它们的长度相等,且从左至右各位上的字符依次相同。

    我们说一个字符串 $T$ 是 $S$ 的**前缀**,当且仅当 $Sleft( 1,lvert T vert ight)=T$。

    两个字符串 $S,T$ 相加 $S+T$ 表示的是在 $S$ 后紧挨着写下 $T$ 得到的长度为 $lvert S vert+lvert T vert$ 的字符串。

    #### 题目描述
    现有一个字符串 $S$。

    Tiffany 将从中划出 $n_a$ 个子串作为 A 类串,第 $i$ 个($1leq ileq n_a$)为 $A_i = Sleft( la_i, ra_i ight)$。

    类似地,Yazid 将划出 $n_b$ 个子串作为 B 类串,第 $i$ 个($1leq ileq n_b$)为 $B_i = Sleft( lb_i, rb_i ight)$。

    现额外给定 $m$ 组支配关系,每组支配关系 $left( x,y ight)$ 描述了第 $x$ 个 A 类串**支配**第 $y$ 个 B 类串。

    求一个**长度最大**的目标串 $T$,使得存在一个串 $T$ 的分割 $T=t_1 + t_2 +dots +t_k$($kgeq 0$)满足:

    - 分割中的每个串 $t_i$ 均为 A 类串:即存在一个与其相等的 A 类串,不妨假设其为 $t_i = A_{id_i}$。
    - 对于分割中所有相邻的串 $t_i , t_{i+1}$($1leq i < k$),都有存在一个 $A_{id_i}$ 支配的 B 类串,使得该 B 类串为 $t_{i+1}$ 的前缀。

    方便起见,你只需要输出这个最大的长度即可。

    特别地,如果存在无限长的目标串(即对于任意一个正整数 $n$,都存在一个满足限制的长度超过 $n$ 的串),请输出 $-1$。

    【输入格式】

    从标准输入读入数据。

    单个测试点中包含多组数据,输入的第一行包含一个非负整数 $T$ 表示数据组数。接下来依次描述每组数据,对于每组数据:

    - 第 $1$ 行一个只包含小写字母的字符串 $S$。
    - 第 $2$ 行一个非负整数 $n_a$,表示 A 类串的数目。接下来 $n_a$ 行,每行 $2$ 个用空格隔开的整数。
    - 这部分中第 $i$ 行的两个数分别为 $la_i,ra_i$,描述第 $i$ 个 A 类串。
    - 保证 $1leq la_ileq ra_ileq lvert S vert$。
    - 接下来一行一个非负整数 $n_b$,表示 B 类串的数目。接下来 $n_b$ 行,每行 $2$ 个用空格隔开的整数。
    - 这部分中第 $i$ 行的两个数分别为 $lb_i,rb_i$,描述第 $i$ 个 B 类串。
    - 保证 $1leq lb_ileq rb_ileq lvert S vert$。
    - 接下来一行一个非负整数 $m$,表示支配关系的组数。接下来 $m$ 行,每行 $2$ 个用空格隔开的整数。
    - 这部分中每行的两个整数 $x,y$,描述一对 $left( x,y ight)$ 的支配关系,具体意义见「题目描述」。
    - 保证 $1leq xleq n_a$,$1leq yleq n_b$。保证所有支配关系两两不同,即不存在两组支配关系的 $x,y$ **均**相同。

    【输出格式】

    输出到标准输出。

    依次输出每组数据的答案,对于每组数据,一行一个整数表示最大串长。特别地,如果满足限制的串可以是无限长的,则请输出 $-1$。

    【样例输入】

    3
    abaaaba
    2
    4 7
    1 3
    1
    3 4
    1
    2 1
    abaaaba
    2
    4 7
    1 3
    1
    7 7
    1
    2 1
    abbaabbaab
    4
    1 5
    4 7
    6 9
    8 10
    3
    1 6
    10 10
    4 6
    5
    1 2
    1 3
    2 1
    3 3
    4 1

    【样例输出】

    7
    -1
    13

    【样例解释】

    对于第 $1$ 组数据,A 类串有 `aaba` 与 `aba`,B 类串有 `aa`,且 $A_2$ 支配 $B_1$。我们可以找到串 `abaaaba`,它可以拆分成 $A_2 + A_1$,且 $A_1$ 包含由 $A_2$ 所支配的 $B_1$ 作为前缀。可以证明不存在长度更大的满足限制的串。

    对于第 $2$ 组数据,与第 $1$ 组数据唯一不同的是,唯一的 B 类串为 `a`。容易证明存在无限长的满足限制的串。

    对于第 $3$ 组数据,容易证明 `abbaabbaaaabb` 是最长的满足限制的串。

    【数据范围与提示】

    |$n_a$|$n_b$|$lvert S vert$|测试点|$m$|$lvert A_i vert geq lvert B_j vert$|其他限制|
    |:-:|:-:|:-:|:-:|:-:|:-:|:-:|
    |$leq 100$|$leq 100$|$leq 10^4$|$1$|$leq 10^4$|保证|保证所有 $lvert A_i vert,lvert B_j vertleq 100$|
    |$leq 1000$|$leq 1000$|$leq 2 imes 10^5$|$2sim 3$|$leq 2 imes 10^5$|保证|无|
    |$=1$|$leq 2 imes 10^5$|$leq 2 imes 10^5$|$4$|$=n_b$|保证|无|
    |$leq 2 imes 10^5$|$leq 2 imes 10^5$|$leq 2 imes 10^5$|$5sim 6$|$leq 2 imes 10^5$|保证|保证所有 $ra_i +1=la_{i+1}$|
    |$leq 2 imes 10^5$|$leq 2 imes 10^5$|$leq 2 imes 10^5$|$7sim 8$|$leq 2 imes 10^5$|保证|无|
    |$leq 2 imes 10^5$|$leq 2 imes 10^5$|$leq 2 imes 10^5$|$9sim 10$|$leq 2 imes 10^5$|不保证|无|

    为了方便你的阅读,我们把**测试点编号**放在了表格的中间,请你注意这一点。

    表格中的 $lvert A_i vert ge lvert B_j vert$ 指的是**任意** B 类串的长度不超过**任意** A 类串的长度。

    对于所有测试点,保证:$Tleq 100$,且对于测试点内所有数据,$lvert S vert,n_a,n_b,m$ 的**总和**分别不会超过**该测试点中对应**的**单组数据的限制**的 $10$ 倍。比如,对于第 1 组测试点,就有 $sum n_aleq 10 imes 100=1000$ 等。特别地,我们规定对于测试点 4,有 $Tleq 10$。

    对于所有测试点中的每一组数据,保证:$1leq lvert S vertleq 2 imes 10^5$,$n_a , n_bleq 2 imes 10^5$,$mleq 2 imes 10^5$。

    #### 提示
    十二省联考命题组温馨提醒您:

    **数据千万条,清空第一条。**

    **多测不清空,爆零两行泪。**

    题解

    首先想到的是暴力判断 $ b_j $ 是否为 $ a_i $ 前缀,效率为 $ O(n^2) $,卡一卡能过前 $ 40 \% $

    考虑优化寻找过程,如果将串反过来,那么前缀就变成了后缀,那么就想到了后缀自动机

    对于后缀自动机的每一个节点,都是其子树的前缀,那么直接按着 parent 树建图即可,可以过 $ 80 \% $

    但上述做法是错的,因为 $ |a_i|>|b_j| $,所以当节点 $ x $ 有 $ |b_1|=5,|a_1|=6,|b_2|=7 $ 时,$ a_1 $ 会有一条连向 $ b_2 $ 的边,直接 GG

    考虑修改建图的过程,将属于 $ x $ 的 $ a,b $ 排序,由 $ b $ 小的向大的连边,每一个 $ a $ 连向最大的比它小的 $ b $,这样子就可以避免以上的问题了,并且每一个 $ b $ 仅向他的儿子的 $ b $ 的结尾连边,这样子边数的复杂度为 $ O(n) $

    然后在建出的图跑 DAG+DP,如果有环就是 -1,不然就是最长路

    时间效率:$ O(nlogn) $,主要在建后缀自动机和求对应的节点上

    然后在 $dis[v=e[k].to]=max(dis[v],dis[now]+len[now])$ 上调到自闭,因为评测环境里从后往前做

    数据千万条,清空第一条。

    多测不清空,爆零两行泪

    代码

     1 #include<bits/stdc++.h>
     2 #define LL long long
     3 #define pb push_back
     4 #define _(d) while(d(isdigit(ch=getchar())))
     5 using namespace std;
     6 int R(){
     7     int x;bool f=1;char ch;_(!)if(ch=='-')f=0;x=ch^48;
     8     _()x=(x<<3)+(x<<1)+(ch^48);return f?x:-x;}
     9 const int N=1e6+5;
    10 int n,m,lg,tot,ma,mb,head[N],dg[N],cnt,h[N],A[N],B[N];
    11 struct edge{int to,nex;}e[N];
    12 int las,Rt,tmp,fa[N][22],tr[N][28],len[N],id[N];
    13 bool fl[N];LL dis[N];
    14 char ch[N];
    15 vector<int>g[N];queue<int> q;
    16 void clean(){
    17     tmp=0;
    18     memset(fa,0,sizeof fa);
    19     memset(tr,0,sizeof tr);
    20     memset(len,0,sizeof len);
    21     memset(fl,0,sizeof fl);
    22     memset(head,0,sizeof head);
    23     memset(dg,0,sizeof dg);
    24     memset(dis,0,sizeof dis);
    25 }
    26 void add(int s,int t){
    27     e[++cnt]=(edge){t,head[s]},head[s]=cnt,dg[t]++;}
    28 void extend(int c){
    29     int p=las,np=las=++tmp,q,nq;
    30     len[np]=len[p]+1;
    31     while(!tr[p][c]&&p)tr[p][c]=np,p=fa[p][0];
    32     if(!p)return void(fa[np][0]=Rt);
    33     if(len[p]+1==len[q=tr[p][c]])
    34         return void(fa[np][0]=q);
    35     len[nq=++tmp]=len[p]+1;
    36     memcpy(tr[nq],tr[q],sizeof tr[q]);
    37     fa[nq][0]=fa[q][0],fa[q][0]=fa[np][0]=nq;
    38     while(p&&tr[p][c]==q)tr[p][c]=nq,p=fa[p][0];
    39     return;
    40 }
    41 void work(int k,int L,bool f){
    42     for(int i=lg;~i;i--)
    43         if(len[fa[k][i]]>=L)k=fa[k][i];
    44     fl[++tot]=f,len[tot]=L,g[k].pb(tot);
    45 }
    46 bool cmp(int a,int b){return len[a]==len[b]?fl[a]>fl[b]:len[a]>len[b];}
    47 LL topu(){
    48     LL ans=0;
    49     for(int i=1;i<=tot;i++){
    50         if(!dg[i])q.push(i);
    51         if(!fl[i])len[i]=0;
    52     }
    53     while(!q.empty()){
    54         int now=q.front();q.pop();
    55         ans=max(ans,dis[now]+len[now]);
    56         for(int k=head[now];k;k=e[k].nex){
    57             int v=e[k].to;
    58             dis[v]=max(dis[v],dis[now]+len[now]);
    59             if(!(--dg[v]))q.push(v);
    60         }
    61     }
    62     for(int i=1;i<=tot;i++)if(dg[i])return -1;
    63     return ans;
    64 }
    65 int main(){
    66     for(int T=R();T--;){
    67         clean();
    68         scanf("%s",ch+1),n=strlen(ch+1);
    69         las=Rt=++tmp;
    70         for(int i=n;i;i--)
    71             extend(ch[i]-'a'),id[i]=las;
    72         lg=log2(tmp)+1;
    73         for(int j=1;j<=lg;j++)
    74             for(int i=1;i<=tmp;i++)
    75                 fa[i][j]=fa[fa[i][j-1]][j-1];
    76         for(int i=1;i<=tmp;i++)g[i].clear();
    77         tot=tmp,ma=R();
    78         for(int i=1,l,r;i<=ma;i++)
    79             l=R(),r=R(),work(id[l],r-l+1,1),A[i]=tot;
    80         mb=R();
    81         for(int i=1,l,r;i<=mb;i++)
    82             l=R(),r=R(),work(id[l],r-l+1,0),B[i]=tot;
    83         cnt=0;
    84         for(int i=1;i<=tmp;i++)sort(g[i].begin(),g[i].end(),cmp);
    85         for(int i=1;i<=tmp;i++){
    86             int now=i;
    87             for(int v,j=g[i].size()-1;~j;j--){
    88                 add(now,v=g[i][j]);
    89                 if(!fl[v])now=v;
    90             }
    91             h[i]=now;
    92         }
    93         for(int i=2;i<=tmp;i++)add(h[fa[i][0]],i);
    94         for(int x,y,i=m=R();i;i--)
    95             x=R(),y=R(),add(A[x],B[y]);
    96         printf("%lld
    ",topu());
    97     }
    98     return 0;
    99 }
    View Code
  • 相关阅读:
    ms日期函数大全
    Sql server char,nchar,varchar与Nvarchar的区别
    clientX pageX
    jswindow对象的方法和属性资料
    Asp.Net中不修改IIS实现URL重写,支持任意扩展名及无扩展名
    该行已经属于另一个表的解决方法
    dopostBack机制(转)
    js触发asp.net的Button的Onclick事件
    Value、ReadString、ReadContentAsString、ReadElementContentAsString 区别
    有关元素元素位置的属性
  • 原文地址:https://www.cnblogs.com/chmwt/p/10667133.html
Copyright © 2020-2023  润新知