zoukankan      html  css  js  c++  java
  • [bzoj1396]识别子串

    [bzoj1396]识别子串

    题面:

    看起来有点吓人实则不然

    用SA或是SAM都可以过

    SAM做法:

    (哪天有空再补)

    SA做法:

    求完SA之后,对于每一个后缀$i$

    以这个后缀为起点的最短唯一子串长度应该是$max(hei[i],hei[i+1])+1$

    之后用线段树覆盖对应区间就行

    ⑨:Baka Baka~

    当然如果一个后缀为起点没有唯一子串的要特判一下

    对于这样的后缀就不进行线段树覆盖

    ⑩:是~这样吗~

    到这里时我自己突然想到不对了

    假设一个后缀的最短唯一子串为$s(i,j)$,那么在$j$后面的字符怎么办?

    因为这个最短唯一子串对它后面的每一位$k$也有着$k-i+1$的贡献

    处理方法

    ans[i]=min(ans[i],ans[i-1]+1)

    本题完结

      1 #include<cstdio>
      2 #include<cstring>
      3 const int N=100011;
      4 char s[N];
      5 int n;
      6 
      7 int max(int a,int b){return a>b?a:b;}
      8 int min(int a,int b){if(!a) return b;if(!b) return a;return a<b?a:b;}
      9 
     10 int sa[N],rank[N],hei[N];
     11 int buk[N],lst[N];
     12 bool cmp(int x,int y,int k)
     13 {
     14     if(x+k>n||y+k>n) return 0;
     15     return rank[x]==rank[y]&&rank[x+k]==rank[y+k];
     16 }
     17 void getsa()
     18 {
     19     int cnt=0;
     20     for(int i=1;i<=n;i++) buk[s[i]]++;
     21     for(int i=1;i<128;i++) if(buk[i]) lst[i]=++cnt;
     22     for(int i=1;i<128;i++) buk[i]+=buk[i-1];
     23     for(int i=1;i<=n;i++)
     24     {
     25         rank[i]=lst[s[i]];
     26         sa[buk[s[i]]--]=i;
     27     }
     28     for(int k=1;cnt!=n;k<<=1)
     29     {
     30         for(int i=1;i<=n;i++) buk[i]=0;
     31         for(int i=1;i<=n;i++) buk[rank[i]]++;
     32         for(int i=1;i<=n;i++) buk[i]+=buk[i-1];
     33         for(int i=n;i;i--)
     34             if(sa[i]>k) lst[sa[i]-k]=buk[rank[sa[i]-k]]--;
     35         for(int i=1;i<=k;i++)
     36             lst[n-i+1]=buk[rank[n-i+1]]--;
     37         for(int i=1;i<=n;i++) sa[lst[i]]=i;
     38         cnt=0;
     39         for(int i=1;i<=n;i++) lst[sa[i]]=cmp(sa[i],sa[i-1],k)?cnt:++cnt;
     40         for(int i=1;i<=n;i++) rank[i]=lst[i];
     41     }
     42 }
     43 void gethei()
     44 {
     45     for(int i=1;i<=n;i++)
     46     {
     47         if(rank[i]==1) continue;
     48         for(int j=max(1,hei[rank[i-1]]-1);;j++)
     49         {
     50             if(s[i+j-1]==s[sa[rank[i]-1]+j-1]) hei[rank[i]]=j;
     51             else break;
     52         }
     53     }
     54 }
     55 
     56 struct mokou
     57 {
     58     int v[N<<2];
     59     void fuckdown(int px)
     60     {
     61         v[px<<1]=min(v[px<<1],v[px]);
     62         v[px<<1|1]=min(v[px<<1|1],v[px]);
     63         return;
     64     }
     65     void cover(int l,int r,int c,int px,int pl,int pr)
     66     {
     67         if(l<=pl&&r>=pr)
     68         {
     69             v[px]=min(v[px],c);
     70             return;
     71         }
     72         fuckdown(px);
     73         int mid=(pl+pr)>>1;
     74         if(l<=mid) cover(l,r,c,px<<1,pl,mid);
     75         if(r>mid) cover(l,r,c,px<<1|1,mid+1,pr);
     76         return;
     77     }
     78     int query(int x,int px,int pl,int pr)
     79     {
     80         if(pl==x&&pr==x) return v[px];
     81         fuckdown(px);
     82         int mid=(pl+pr)>>1;
     83         if(x<=mid) return query(x,px<<1,pl,mid);
     84         else return query(x,px<<1|1,mid+1,pr);
     85     }
     86 }tr;
     87 int ans[N];
     88 
     89 int main()
     90 {
     91     scanf("%s",s+1);
     92     n=strlen(s+1);
     93     getsa();
     94     gethei();
     95     for(int i=1;i<=n;i++)
     96     {
     97         if(sa[i]+max(hei[i],hei[i+1])>n) continue;
     98 
     99         tr.cover(sa[i],sa[i]+max(hei[i],hei[i+1]),max(hei[i],hei[i+1])+1,1,1,n);
    100     }
    101     for(int i=1;i<=n;i++)
    102         ans[i]=tr.query(i,1,1,n);
    103     for(int i=2;i<=n;i++) ans[i]=min(ans[i],ans[i-1]+1);
    104     for(int i=1;i<=n;i++) printf("%d
    ",ans[i]);
    105     return 0;
    106 }
    Orz
  • 相关阅读:
    jmeter测试接口--form表单提交请求(解决请求传参为空的问题)
    jmeter测试接口-打开很多TCP的连接数TIME_WAIT状态(Linux环境)导致报错的解决方法
    Jmeter 事务下的if控制器和无事务下的if控制器是否有不同 (业务实现3:2的补充)
    Jmeter if控制器的使用
    Jmeter 文件格式的参数化
    CentOS7学习笔记--tomcat9环境安装
    CentOS7学习笔记--PHP环境安装
    CentOS学习笔记—启动、ROOT密码
    虚拟机硬盘扩容
    win7如何设置某个软件不弹出用户账户控制
  • 原文地址:https://www.cnblogs.com/rikurika/p/10776389.html
Copyright © 2011-2022 走看看