zoukankan      html  css  js  c++  java
  • [BZOJ4556][Tjoi2016&Heoi2016]字符串 主席树+二分+倍增+后缀自动机

    4556: [Tjoi2016&Heoi2016]字符串

    Time Limit: 20 Sec  Memory Limit: 128 MB
    Submit: 1215  Solved: 484
    [Submit][Status][Discuss]

    Description

    佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物。生日礼物放在一个神奇的箱子中。箱子外边写了
    一个长为n的字符串s,和m个问题。佳媛姐姐必须正确回答这m个问题,才能打开箱子拿到礼物,升职加薪,出任CE
    O,嫁给高富帅,走上人生巅峰。每个问题均有a,b,c,d四个参数,问你子串s[a..b]的所有子串和s[c..d]的最长公
    共前缀的长度的最大值是多少?佳媛姐姐并不擅长做这样的问题,所以她向你求助,你该如何帮助她呢?

    Input

    输入的第一行有两个正整数n,m,分别表示字符串的长度和询问的个数。接下来一行是一个长为n的字符串。接下来
    m行,每行有4个数a,b,c,d,表示询问s[a..b]的所有子串和s[c..d]的最长公共前缀的最大值。1<=n,m<=100,000,
    字符串中仅有小写英文字母,a<=b,c<=d,1<=a,b,c,d<=n
     

    Output

     对于每一次询问,输出答案。

    Sample Input

    5 5
    aaaaa
    1 1 1 5
    1 5 1 1
    2 3 2 3
    2 4 2 3
    2 3 2 4

    Sample Output

    1
    1
    2
    2
    2

    HINT

     

    Source

     
     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cmath>
     5 #include<algorithm>
     6 #include<cstdio>
     7 #define maxn 200010
     8 using namespace std;
     9 int n,m;
    10 struct data {
    11     int last,cnt;
    12     int link[maxn],step[maxn],son[maxn][26];
    13     int v[maxn],pos[maxn],fa[maxn][20],w[maxn];
    14     int s[maxn*20][2],rt[maxn],t;
    15     void insert(int &k,int l,int r,int x) {
    16         k=++t;
    17         if(l==r) return;
    18         int mid=l+r>>1;
    19         if(x<=mid) insert(s[k][0],l,mid,x);
    20         else insert(s[k][1],mid+1,r,x);
    21     }
    22     int merge(int x,int y) {
    23         if(!x||!y) return x+y;
    24         int z=++t;
    25         s[z][0]=merge(s[x][0],s[y][0]);s[z][1]=merge(s[x][1],s[y][1]);
    26         return z;
    27     }
    28     bool query(int x,int l,int r,int L,int R) {
    29         if(!x) return 0;
    30         if(L<=l&&R>=r) return 1;
    31         int mid=l+r>>1;
    32         if (R<=mid) return query(s[x][0],l,mid,L,R);  
    33         else if(L>mid) return query(s[x][1],mid+1,r,L,R);  
    34         else return query(s[x][0],l,mid,L,mid)||query(s[x][1],mid+1,r,mid+1,R);  
    35     }
    36     data() {last=cnt=1;}
    37     void extend(int x,int id) {
    38         int p=last,np=last=++cnt;step[np]=step[p]+1;insert(rt[np],1,n,id);w[id]=np;
    39         while(p&&!son[p][x]) son[p][x]=np,p=link[p];
    40         if(!p) link[np]=1;
    41         else {
    42             int q=son[p][x];
    43             if(step[q]==step[p]+1) link[np]=q;
    44             else {
    45                 int nq=++cnt;
    46                 memcpy(son[nq],son[q],sizeof(son[q]));
    47                 link[nq]=link[q];
    48                 link[q]=link[np]=nq;
    49                 step[nq]=step[p]+1;
    50                 while(p&&son[p][x]==q) son[p][x]=nq,p=link[p];
    51             }
    52         }
    53     }
    54     void pre() {
    55         for(int i=1;i<=cnt;i++) v[step[i]]++;
    56         for(int i=1;i<=cnt;i++) v[i]+=v[i-1];
    57         for(int i=cnt;i;i--) pos[v[step[i]]--]=i;
    58         for(int i=cnt;i;i--) {
    59             rt[link[pos[i]]]=merge(rt[link[pos[i]]],rt[pos[i]]);
    60             fa[pos[i]][0]=link[pos[i]];
    61         }
    62         for(int j=1;j<=18;j++) for(int i=1;i<=cnt;i++) fa[i][j]=fa[fa[i][j-1]][j-1];
    63     }
    64     bool check(int mid,int x,int l,int r) {
    65         for(int i=18;i>=0;i--) if(step[fa[x][i]]>=mid) x=fa[x][i];
    66         return query(rt[x],1,n,l,r);
    67     }
    68 }a;
    69 char ch[maxn];
    70 int main() {
    71     scanf("%d%d",&n,&m);
    72     scanf("%s",ch+1);reverse(ch+1,ch+n+1);
    73     for(int i=1;i<=n;i++) a.extend(ch[i]-'a',i);
    74     a.pre();
    75     for(int i=1;i<=m;i++) {
    76         int a1,b1,c1,d1;scanf("%d%d%d%d",&a1,&b1,&c1,&d1);
    77         a1=n-a1+1;b1=n-b1+1;c1=n-c1+1;d1=n-d1+1;
    78         swap(a1,b1);swap(c1,d1);
    79         int l=1,r=min(d1-c1+1,b1-a1+1);
    80         while(l<=r) {
    81             int mid=l+r>>1;
    82             if(a.check(mid,a.w[d1],a1+mid-1,b1)) l=mid+1;
    83             else r=mid-1;
    84         }
    85         printf("%d
    ",l-1);
    86     }
    87 }
    View Code
    O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~
  • 相关阅读:
    Linux网络相关命令firewalld和netfilter、iptables 使用(6/22)
    Linux时间设置与iptables命令
    负载均衡集群ipvsadm命令及基本用法
    LVS原理详解以及部署
    linux比较两个文件的不同(6/21)
    如何使用sql函数平均值、总数、最小值、最大值
    python中数据类型转换
    使用 getopt 处理命令行长参数
    Mysql常用命令行大全
    C#控制台程序使用Log4net日志组件
  • 原文地址:https://www.cnblogs.com/wls001/p/8404816.html
Copyright © 2011-2022 走看看