zoukankan      html  css  js  c++  java
  • 字符串问题

    字符串问题

    题目背景
    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$。


    solution

    首先考虑暴力建图:A向支配的B连,B向前缀包含它的连。然后跑拓扑序dp。 40‘(我这咋只有20)

    用sam优化:用反串建,则x为x的后代的前缀。

    那么可以把par树连起来,然后支配边照常连,边数2n 。80’

    不能满分是因为如果b[i]>a[i],连边后可能两个B被压在了同一个节点,但是一个可以被支配,一个不行。

    把一个sam节点上的所有串按长度排序,从长度小的开始连,每次当前点与它的上一个b点。相当于串了起来。

    这样子如果A能支配某一个B1,那么他只会连到这个B1,然后再间接的连到一个比B1长的B2...

    而如果B2是某个串的前缀,那么B1也是。

    于是就好了。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<algorithm>
      6 #include<cmath>
      7 #include<vector>
      8 #include<queue>
      9 #define maxn 800005
     10 using namespace std;
     11 int T,na,nb,m,cnt,rt,la,al;
     12 int head[maxn],tot,pl[maxn],f[maxn][22],out[maxn],top[maxn];
     13 long long dp[maxn];char ch[maxn];
     14 vector<int>G[maxn],p[maxn];
     15 struct node{int v,nex;}e[maxn*2];
     16 struct no{
     17     int par,nex[26],Max,ed;
     18 }s[maxn];
     19 struct Node{
     20     int l,r,len;
     21 }a[maxn],b[maxn];
     22 void Q(){
     23     for(int i=0;i<=cnt+na+nb;i++){
     24         head[i]=pl[i]=0;
     25         out[i]=0;G[i].clear();p[i].clear();
     26         dp[i]=top[i]=0;
     27     }
     28     cnt=rt=la=1;tot=0;
     29     memset(f,0,sizeof f);
     30     memset(s,0,sizeof s);
     31 }
     32 void ins(int c,int id){
     33     int np=++cnt,p=la;la=np;
     34     s[np].ed=id;s[np].Max=s[p].Max+1;pl[id]=cnt;
     35     for(;p&&!s[p].nex[c];p=s[p].par)s[p].nex[c]=np;
     36     if(!p)s[np].par=rt;
     37     else {
     38         int q=s[p].nex[c];
     39         if(s[q].Max==s[p].Max+1)s[np].par=q;
     40         else {
     41             int nq=++cnt;
     42             s[nq].Max=s[p].Max+1;s[nq].par=s[q].par;
     43             for(int i=0;i<26;i++)s[nq].nex[i]=s[q].nex[i];
     44             s[q].par=s[np].par=nq;
     45             for(;s[p].nex[c]==q;p=s[p].par)s[p].nex[c]=nq;
     46         }
     47     }
     48 }
     49 void dfs(int k,int fa){
     50     f[k][0]=fa;
     51     for(int i=0;i<G[k].size();i++)dfs(G[k][i],k);
     52 }
     53 bool cmp(int A,int B){
     54     int xa=A,xb=B;
     55     if(A>cnt+na)A=b[A-cnt-na].len;
     56     else A=a[A-cnt].len;
     57     if(B>cnt+na)B=b[B-cnt-na].len;
     58     else B=a[B-cnt].len; 
     59     return A<B||A==B&&xa>xb;
     60 }
     61 void add(int t1,int t2){
     62     e[++tot].v=t1;e[tot].nex=head[t2];head[t2]=tot;
     63     out[t1]++;
     64 }
     65 void init(){
     66     scanf("%s",ch+1);int len=strlen(ch+1);
     67     for(int i=len;i>=1;i--){
     68         ins(ch[i]-'a',i);
     69     }
     70     scanf("%d",&na);for(int i=1;i<=na;i++)scanf("%d%d",&a[i].l,&a[i].r),a[i].len=a[i].r-a[i].l+1;
     71     scanf("%d",&nb);for(int i=1;i<=nb;i++)scanf("%d%d",&b[i].l,&b[i].r),b[i].len=b[i].r-b[i].l+1;
     72     for(int i=1;i<=cnt;i++)G[s[i].par].push_back(i);
     73     dfs(rt,0);
     74     for(int j=1;j<=20;j++)
     75     for(int i=1;i<=cnt;i++)f[i][j]=f[f[i][j-1]][j-1];
     76     for(int i=1;i<=na;i++){
     77         int t=pl[a[i].l],L=a[i].len;
     78         for(int j=20;j>=0;j--){
     79             int v=f[t][j];if(s[v].Max>=L)t=v;
     80         }
     81         p[t].push_back(cnt+i);
     82     }
     83     for(int i=1;i<=nb;i++){
     84         int t=pl[b[i].l],L=b[i].len;
     85         for(int j=20;j>=0;j--){
     86             int v=f[t][j];if(s[v].Max>=L)t=v;
     87         }
     88         p[t].push_back(cnt+na+i);
     89     }
     90     for(int i=1;i<=cnt;i++)sort(p[i].begin(),p[i].end(),cmp);
     91     
     92     for(int i=1;i<=cnt;i++){
     93         int lb=i;
     94         for(int j=0;j<p[i].size();j++){
     95             int t=p[i][j];
     96             if(t>cnt+na)add(lb,t),lb=t;
     97             else add(lb,t);
     98         }
     99         top[i]=lb;
    100     }
    101     for(int i=1;i<=cnt;i++)
    102     if(s[i].par){
    103         add(top[s[i].par],i);
    104     }
    105     cin>>m;
    106     for(int i=1,t1,t2;i<=m;i++){
    107         scanf("%d%d",&t1,&t2);
    108         add(cnt+t1,cnt+na+t2);
    109     }
    110     al=cnt+na+nb;
    111 }
    112 void tp(){
    113     queue<int>q;
    114     for(int i=1;i<=al;i++)if(!out[i])q.push(i);
    115     while(!q.empty()){
    116         int x=q.front();q.pop();
    117         if(x>cnt&&x<=cnt+na)dp[x]+=a[x-cnt].len;
    118         for(int i=head[x];i;i=e[i].nex){
    119             dp[e[i].v]=max(dp[e[i].v],dp[x]);
    120             if(!(--out[e[i].v]))q.push(e[i].v);
    121         }
    122     }
    123     for(int i=1;i<=al;i++)if(out[i]>0){puts("-1");return;}
    124     long long ans=0;
    125     for(int i=1;i<=al;i++)ans=max(ans,dp[i]);
    126     cout<<ans<<endl;
    127 }
    128 int main(){
    129     cin>>T;
    130     while(T--){
    131         Q();
    132         init();
    133         tp();
    134     }
    135     return 0;
    136 }
    View Code
  • 相关阅读:
    实现a标签按钮完全禁用【转】
    input 内容改变的触发事件【转】
    PHP字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、切割成数组等)【转】
    数列分块入门 4(涉及区间加法,区间求和)
    #6279. 数列分块入门 3(询问区间内小于某个值 xx 的前驱(比其小的最大元素))
    #6278. 数列分块入门 2(询问区间内小于某个值 xx 的元素个数)
    A Simple Problem with Integers POJ
    bzoj3262: 陌上花开(CDQ+树状数组处理三维偏序问题)
    P3806 【模板】点分治1(CDQ分治)
    Toy Train(贪心)
  • 原文地址:https://www.cnblogs.com/liankewei/p/10674675.html
Copyright © 2011-2022 走看看