zoukankan      html  css  js  c++  java
  • 【poj1743】Musical Theme 【后缀自动机】

    题意

     给出一个n个数字的序列,找出相同变化趋势且不重叠的两个最长子串。

    分析

     这个题以前应该用后缀数组+二分做过。学了后缀自动机后可以用后缀自动机搞一下。

      先差分,然后把查分后的数组建SAM。然后对于每个状态记录一个l[u],和r[u],分别代表right集合中,最大的v和最小的v。(这里如果不明白可以去看clj的课件)。

      然后对于每个状态,当这个状态cnt[u]>=2的时候,说明有两个以上的子串,然后min(st[u].len,r[u]-l[u])就是这个状态最长不重叠相同子串的长度。

      

     1 #include <cstring>
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <cstdio>
     5 #include <map>
     6 using namespace std;
     7 const int maxn=20000+100;
     8 const int INF=2147000000;
     9 int s[maxn],a[maxn],n;
    10 struct state{
    11     int len,link;
    12     int next[180];
    13 }st[2*maxn];
    14 int last,cur,sz;
    15 int cnt[2*maxn],l[2*maxn],r[2*maxn],c[2*maxn];
    16 void init(){
    17     sz=1;
    18     last=cur=0;
    19     st[0].len=0;
    20     st[0].link=-1;
    21     memset(st[0].next,0,sizeof(st[0].next));
    22 }
    23 
    24 void build_sam(int c,int pos){
    25     cur=sz++;
    26     st[cur].len=st[last].len+1;
    27     cnt[cur]=1;
    28     l[cur]=r[cur]=pos;
    29     memset(st[cur].next,0,sizeof(st[cur].next));
    30     int p;
    31     for(p=last;p!=-1&&st[p].next[c]==0;p=st[p].link)
    32         st[p].next[c]=cur;
    33     if(p==-1)
    34         st[cur].link=0;
    35     else{
    36         int q=st[p].next[c];
    37         if(st[q].len==st[p].len+1)
    38             st[cur].link=q;
    39         else{
    40             int clone=sz++;
    41             cnt[clone]=r[clone]=0;
    42             l[clone]=127;
    43             st[clone].len=st[p].len+1;
    44             //printf("%d ",st[clone].len);
    45             st[clone].link=st[q].link;
    46             memcpy(st[clone].next,st[q].next,sizeof(st[clone].next));
    47             for(;p!=-1&&st[p].next[c]==q;p=st[p].link){
    48                 st[p].next[c]=clone;
    49             }
    50             st[cur].link=st[q].link=clone;
    51         }
    52     }
    53     last=cur;
    54 }
    55 int cmp(int a,int b){
    56     return st[a].len>st[b].len;
    57 }
    58 
    59 int ans=0;
    60 int main(){
    61     while(scanf("%d",&n)!=EOF&&n){
    62         for(int i=1;i<=n;i++){
    63             scanf("%d",&s[i]);
    64             a[i]=s[i]-s[i-1];
    65         }
    66         init();
    67         for(int i=1;i<=n;i++){
    68             build_sam(a[i]+88,i);
    69             //printf("%d ",a[i]);
    70         }
    71 //        for(int i=0;i<sz;i++)
    72 //            printf("%d ",st[i].len);
    73 //        printf("
    ");
    74         for(int i=0;i<sz;i++)
    75             c[i]=i;
    76         sort(c,c+sz,cmp);
    77         ans=0;
    78         for(int i=0;i<sz;i++){
    79             int o=c[i];
    80             if(st[o].link!=-1){
    81                 cnt[st[o].link]+=cnt[o];
    82                 l[st[o].link]=min(l[st[o].link],l[o]);
    83                 r[st[o].link]=max(r[st[o].link],r[o]);
    84             }
    85          //   printf("%d %d %d %d
    ",cnt[o],st[o].len,l[o],r[o]);
    86             if(cnt[o]>=2&&min(st[o].len,r[o]-l[o])>=4){
    87                 //printf("%d %d
    ",l[o],r[o]);
    88                 ans=max(ans,min(st[o].len,r[o]-l[o]));
    89             }
    90         }
    91         if(ans<4)
    92             printf("0
    ");
    93         else
    94         printf("%d
    ",ans+1);
    95     }
    96 return 0;
    97 }
    View Code
  • 相关阅读:
    手机精准定位,看好你的男朋友
    顶级分享,三端看片的日子来了
    这样的声音谁受的了呀
    白嫖vip电台,资源随意听
    老板止步!这里全是小姐姐
    粉丝福利。无视墙 来看看全世界的网站吧
    利用自己的服务器搭建专属私有云盘&博客园搬家
    Photoshop 2020 安装教程
    TensorFlow基础——常用函数(一)
    Scala基本语法入门
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/9887776.html
Copyright © 2011-2022 走看看