zoukankan      html  css  js  c++  java
  • 【BZOJ1396】识别子串

    题意:

    Description

    Input

    一行,一个由小写字母组成的字符串S,长度不超过10^5

    Output

    L行,每行一个整数,第i行的数据表示关于S的第i个元素的最短识别子串有多长.

    题解:

    先建出SAM,显然right集合大小为1的子串,即在parent树上的叶子节点可以作为识别子串;

    考虑一个这样的子串会对哪些区间产生影响:

    设$l=max[fa[s]]$,$r=max[s]$,显然这个子串出现的位置就是$r$,所以对区间$[1,r]$都有影响;

    但是其中有一段是被$fa[s]$包含的,因此贡献不同,具体来说就是:

    在区间$[1,l-1]$中贡献为$r-i+1$;

    在区间$[l,r]$中贡献为$r-l+1$;

    这里手推一下就好;

    因此开两棵线段树维护修改最小值即可。

    代码:

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cmath>
     6 #include<queue>
     7 #include<set>
     8 #define inf 0x7f7f7f7f
     9 #define eps 1e-9
    10 #define mp make_pair
    11 using namespace std;
    12 typedef long long ll;
    13 typedef double db;
    14 int n,l,r,last=1,rt=1,tot=1,son[200001][26],fa[200001],mx[200001];
    15 bool ch[200001];
    16 char s[100001];
    17 struct seg{
    18     int t[2000001];
    19     seg(){
    20         memset(t,0x7f,sizeof(t));
    21     }
    22     void pd(int u){
    23         if(t[u]!=inf){
    24             t[u*2]=min(t[u*2],t[u]);
    25             t[u*2+1]=min(t[u*2+1],t[u]);
    26             t[u]=inf;
    27         }
    28     }
    29     void updata(int l,int r,int u,int L,int R,int x){
    30         if(L>R)return;
    31         if(L<=l&&r<=R){
    32             t[u]=min(t[u],x);
    33             return;
    34         }
    35         pd(u);
    36         int mid=(l+r)/2;
    37         if(L<=mid)updata(l,mid,u*2,L,R,x);
    38         if(mid<R)updata(mid+1,r,u*2+1,L,R,x);
    39     }
    40     int query(int l,int r,int u,int p){
    41         if(l==r)return t[u];
    42         pd(u);
    43         int mid=(l+r)/2;
    44         if(p<=mid)return query(l,mid,u*2,p);
    45         else return query(mid+1,r,u*2+1,p);
    46     }
    47 }t1,t2;
    48 void extend(int ch){
    49     int p=last,np=++tot;
    50     mx[np]=mx[p]+1;
    51     for(;p&&!son[p][ch];p=fa[p])son[p][ch]=np;
    52     if(!p)fa[np]=rt;
    53     else{
    54         int q=son[p][ch];
    55         if(mx[q]==mx[p]+1)fa[np]=q;
    56         else{
    57             int nq=++tot;
    58             mx[nq]=mx[p]+1;
    59             memcpy(son[nq],son[q],sizeof(son[q]));
    60             fa[nq]=fa[q];
    61             fa[q]=fa[np]=nq;
    62             for(;p&&son[p][ch]==q;p=fa[p])son[p][ch]=nq;
    63         }
    64     }
    65     last=np;
    66 }
    67 int main(){
    68     scanf("%s",s);
    69     n=strlen(s);
    70     for(int i=0;i<n;i++)extend(s[i]-'a');
    71     for(int i=1;i<=tot;i++){
    72         if(fa[i])ch[fa[i]]=true;
    73     }
    74     for(int i=1;i<=tot;i++){
    75         if(!ch[i]){
    76             l=mx[i]-mx[fa[i]],r=mx[i];
    77             t1.updata(1,n,1,1,l-1,r+1);
    78             t2.updata(1,n,1,l,r,r-l+1);
    79         }
    80     }
    81     for(int i=1;i<=n;i++){
    82         printf("%d
    ",min(t1.query(1,n,1,i)-i,t2.query(1,n,1,i)));
    83     }
    84     return 0;
    85 }
  • 相关阅读:
    git 删除已经提交的文件
    IDEA不显示service 服务窗口
    MySQL SQL语句查询结果 多列合并为1列
    Linux远程执行脚本
    mycat 连接命令
    win10 关闭被占用的端口
    ERROR 1045 (HY000): Access denied for user 'root', because password is error
    unblock with 'mysqladmin flush-hosts'
    neo4j数据库cypher查询
    基于websocket的网页实时消息推送与在线聊天(上篇)
  • 原文地址:https://www.cnblogs.com/dcdcbigbig/p/10129504.html
Copyright © 2011-2022 走看看