• bzoj1396: 识别子串


      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cmath>
      5 #include <algorithm>
      6 #define maxn 100005
      7 #define inf 100000000
      8 using namespace std;
      9 char st[maxn];
     10 int n,tot,last,root,sum[maxn<<1],tmp[maxn<<1],fa[maxn<<1],son[maxn<<1][26],dist[maxn<<1],ri[maxn<<1],pos[maxn<<1];
     11 struct Tsegment{
     12     void prepare(){tot=last=root=1,memset(ri,0,sizeof(ri));}
     13     int newnode(int x){
     14         dist[++tot]=x; return tot;
     15     }
     16     void add(int op,int x){
     17         int p=last,np=newnode(dist[p]+1); last=np; ri[np]=1; pos[np]=op;
     18         for (;p&&!son[p][x];p=fa[p]) son[p][x]=np;
     19         if (p==0) fa[np]=root;
     20         else{
     21             int q=son[p][x];
     22             if (dist[p]+1==dist[q]) fa[np]=q;
     23             else{
     24                 int nq=newnode(dist[p]+1);
     25                 memcpy(son[nq],son[q],sizeof(son[q]));
     26                 fa[nq]=fa[q],fa[q]=fa[np]=nq;
     27                 for (;p&&son[p][x]==q;p=fa[p]) son[p][x]=nq;
     28             }
     29         }
     30     }
     31 }SAM;
     32 struct Fsegment{
     33     int l,r,lazy,val;
     34 }tree1[maxn*8];
     35 struct date{
     36     void build(int k,int l,int r){
     37         tree1[k].lazy=tree1[k].val=inf; tree1[k].l=l,tree1[k].r=r;
     38         if (l==r) return;
     39         int mid=(l+r)/2;
     40         build(k*2,l,mid),build(k*2+1,mid+1,r);
     41     }
     42     void change(int k,int l,int r,int x,int y,int z){
     43         if (x>y) return;
     44         if (tree1[k].lazy!=inf){
     45             if (tree1[k*2].l) pushdown(k*2,tree1[k].lazy);
     46             if (tree1[k*2+1].l) pushdown(k*2+1,tree1[k].lazy);
     47             tree1[k].lazy=inf;
     48         }
     49         if (l>=x&&r<=y){
     50             pushdown(k,z);
     51             return;
     52         } int mid=(l+r)/2;
     53         if (x<=mid) change(k*2,l,mid,x,y,z);
     54         if (y>mid) change(k*2+1,mid+1,r,x,y,z);
     55     }
     56     void pushdown(int k,int x){
     57         tree1[k].lazy=min(tree1[k].lazy,x);
     58         if (tree1[k].l==tree1[k].r) tree1[k].val=min(tree1[k].val,tree1[k].lazy);
     59     }
     60     int query(int k,int l,int r,int x){
     61         if (tree1[k].lazy!=inf){
     62             if (tree1[k*2].l) pushdown(k*2,tree1[k].lazy);
     63             if (tree1[k*2+1].l) pushdown(k*2+1,tree1[k].lazy);
     64             tree1[k].lazy=inf;
     65         }
     66         if (l==r&&r==x) return tree1[k].val;
     67         int mid=(l+r)>>1,ans=inf;
     68         if (x<=mid) ans=min(ans,query(k*2,l,mid,x));
     69         else ans=min(ans,query(k*2+1,mid+1,r,x));
     70         return ans;
     71     }
     72 }Tree1;
     73 struct Ksegment{
     74     int l,r,val,lazy;
     75 }tree[maxn*8];
     76 struct Graph{
     77     void build(int k,int l,int r){
     78         tree[k].l=l,tree[k].r=r,tree[k].lazy=tree[k].val=inf;
     79         if (l==r) return; int mid=(l+r)/2;
     80         build(k*2,l,mid),build(k*2+1,mid+1,r);
     81     }
     82     void change(int k,int l,int r,int x,int y,int z){
     83         if (x>y) return;
     84         if (tree[k].lazy!=inf){
     85             if (tree[k*2].l) pushdown(k*2,tree[k].lazy);
     86             if (tree[k*2+1].l) pushdown(k*2+1,tree[k].lazy);
     87             tree[k].lazy=inf;
     88         }
     89         if (l>=x&&r<=y){
     90             pushdown(k,z);
     91             return;
     92         } int mid=(l+r)>>1;
     93         if (x<=mid) change(k*2,l,mid,x,y,z);
     94         if (y>mid) change(k*2+1,mid+1,r,x,y,z);
     95     }
     96     void pushdown(int k,int x){
     97         tree[k].lazy=min(tree[k].lazy,x);
     98         if (tree[k].l==tree[k].r) tree[k].val=min(tree[k].val,tree[k].lazy);
     99     }
    100     int query(int k,int l,int r,int x){
    101         if (tree[k].lazy!=inf){
    102             if (tree[k*2].l) pushdown(k*2,tree[k].lazy);
    103             if (tree[k*2+1].r) pushdown(k*2+1,tree[k].lazy);
    104             tree[k].lazy=inf;
    105         }
    106         if (l==r&&r==x) return tree[k].val;
    107         int mid=(l+r)>>1,ans=inf;
    108         if (x<=mid) ans=min(ans,query(k*2,l,mid,x));
    109         else ans=min(ans,query(k*2+1,mid+1,r,x));
    110         return ans;
    111     }
    112 }Tree;
    113 int main(){
    114     scanf("%s",st+1),n=strlen(st+1);
    115     SAM.prepare();
    116     for (int i=1;i<=n;i++) SAM.add(i,st[i]-'a');
    117     memset(sum,0,sizeof(sum));
    118     for (int i=1;i<=tot;i++) sum[dist[i]]++;
    119     for (int i=1;i<=tot;i++) sum[i]+=sum[i-1];
    120     for (int i=1;i<=tot;i++) tmp[sum[dist[i]]--]=i;
    121     for (int i=tot,x;i>=1;i--){
    122         x=tmp[i];
    123         if (fa[x]) ri[fa[x]]+=ri[x];
    124     }
    125     ri[root]=0;
    126     Tree1.build(1,1,n);
    127     Tree.build(1,1,n);
    128     for (int i=1;i<=tot;i++){
    129         if (ri[i]!=1) continue;
    130         int x=pos[i],y=dist[i],z=dist[fa[i]]+1;
    131         Tree1.change(1,1,n,x-y+1,x-z+1,x);   //第一棵线段树按位置,记得减
    132         Tree.change(1,1,n,x-z+2,x,z);    //第二棵线段树按长度
    133     }
    134     for (int i=1;i<=n;i++){
    135         printf("%d
    ",min(Tree1.query(1,1,n,i)-i+1,Tree.query(1,1,n,i)));
    136     }
    137     return 0;
    138 }
    139 
    View Code

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1396

    题目大意:

    做法;看到题目中所说的T在S中只出现过一次,就很容易想到用后缀自动机嘛,显然就是right值为一的状态,而且right值为一的状态只能是每次add时第一个新建的点,这很显然嘛,这就很方便记录了。然后再用线段树维护一下最小值,稍微想一下就行,当时我竟然是很快就想到了,不过我inf开小了,狂WA不止。

    后缀自动机+线段树。

  • 相关阅读:
    hbase伪分布式安装
    按照《权威指南》的例子求最低温度并且修改默认调度器为FairScheduler
    利用hadoop1.x集群进行探索性实验(四)~(五)【重复格式化NN后,DN不能启动】【控制namenode检查点发生的频率】
    利用hadoop1.x集群进行探索性实验(三)【修改HDFS块大小】
    利用hadoop1.x集群进行探索性实验(二)【模拟namenode崩溃,通过secondary namenode恢复namenode】
    利用hadoop1.x集群进行探索性实验(一)【对WEB监控界面增加安全机制】
    本地编译64位hadoop并进行部署。
    hadoop完全分布式安装
    storm集群和zookeeper集群的部署过程
    查看电脑连接过的wifi密码
  • 原文地址:https://www.cnblogs.com/OYzx/p/5559473.html
Copyright © 2020-2023  润新知