zoukankan      html  css  js  c++  java
  • POJ2774 后缀自动机&后缀数组

    http://poj.org/problem?id=2774

    题目大意就是给两个字符串,求最长公共子串。好像可以哈希切掉,但是为了练一练后缀数组以及学一学后缀自动机,我用不同方法终于A掉了这道题。

    后缀数组:就是求出height数组然后扫一遍,求出满足条件的最大值(满足条件是指height所指的两个后缀要没有公共部分),是后缀数组的水题

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 char tmp[100005],s[200005];
     6 int n,sa[200005],rak[200005],height[200005],t[200005],t2[200005],c[300];
     7 void build_sa(int m)
     8 {
     9     int *x=t,*y=t2,p;
    10     for(int i=0;i<m;i++)c[i]=0;
    11     for(int i=0;i<n;i++)c[x[i]=s[i]]++;
    12     for(int i=0;i<m;i++)c[i]+=c[i-1];
    13     for(int i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
    14     for(int k=1;k<=n;k<<=1)
    15     {
    16         p=0;
    17         for(int i=n-k;i<n;i++)y[p++]=i;
    18         for(int i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k;
    19         for(int i=0;i<m;i++)c[i]=0;
    20         for(int i=0;i<n;i++)c[x[y[i]]]++;
    21         for(int i=0;i<m;i++)c[i]+=c[i-1];
    22         for(int i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
    23         swap(x,y);
    24         p=1;x[sa[0]]=0;
    25         for(int i=1;i<n;i++)
    26         x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;
    27         if(p>=n)break;
    28         m=p;
    29     }
    30 }
    31 void printsa()
    32 {
    33     puts("");
    34     for(int i=0;i<n;i++)
    35     {
    36         char *ss=s+sa[i];
    37         while(*ss)putchar(*ss++);
    38         puts("");
    39     }
    40 }
    41 void get_height()
    42 {
    43     for(int i=0;i<n;i++)rak[sa[i]]=i;
    44     int k=0;
    45     for(int i=0;i<n;i++)
    46     {
    47         if(k)k--;
    48         if(rak[i]==0){height[rak[i]]=k;continue;}
    49         int j=sa[rak[i]-1];
    50         while(s[i+k]==s[j+k])k++;
    51         height[rak[i]]=k;
    52     }
    53 }
    54 int main()
    55 {
    56     int mid;
    57     while(scanf("%s",tmp)>0)
    58     {
    59         memset(s,0,sizeof(s));
    60         mid=strlen(tmp);
    61         tmp[mid]='$';
    62         strcat(s,tmp);
    63         scanf("%s",tmp);
    64         tmp[strlen(tmp)+1]='';
    65         tmp[strlen(tmp)]='#';
    66         strcat(s,tmp);
    67         n=strlen(s);
    68         build_sa(130);
    69         //printsa();
    70         get_height();
    71         int ans=0;
    72         for(int i=1;i<n;i++)if(height[i]>ans&&((sa[i-1]<mid&&sa[i]>mid)||(sa[i-1]>mid&&sa[i]<mid)))ans=height[i];
    73         printf("%d
    ",ans);
    74     }
    75     return 0;
    76 }

    后缀自动机:基本上是一道模板题,用第一个字符串建好后缀自动机,再用第二个字符串匹配。。。感觉和AC自动机差不多(感觉数组写法比指针写法好看多了)

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 const int N=101000;
     7 char s[N],t[N];
     8 int last,son[N<<1][30],dep[N<<1],pre[N<<1],lens,lent,tot,rt;
     9 void SAM(int alp)
    10 {
    11     int u=last;dep[++tot]=dep[last]+1;
    12     last=tot;
    13     while(u&&!son[u][alp])son[u][alp]=last,u=pre[u];
    14     if(!u)pre[last]=rt;
    15     else
    16     {
    17         int v=son[u][alp];
    18         if(dep[v]==dep[u]+1)pre[last]=v;
    19         else
    20         {
    21             dep[++tot]=dep[u]+1;
    22             int nv=tot;
    23             memcpy(son[nv],son[v],sizeof(son[nv]));
    24             pre[nv]=pre[v];pre[v]=pre[last]=nv;
    25             while(u&&son[u][alp]==v)son[u][alp]=nv,u=pre[u];
    26         }
    27     }
    28 }
    29 int solve()
    30 {
    31     int cur,tmp=0,ret=0;
    32     cur=rt=last=++tot;
    33     for(int i=1;i<=lens;i++)SAM(s[i]-'a');
    34     for(int i=1;i<=lent;i++)
    35     {
    36         if(son[cur][t[i]-'a']){cur=son[cur][t[i]-'a'];tmp++;}
    37         else
    38         {
    39             while(cur&&!son[cur][t[i]-'a'])cur=pre[cur];
    40             if(!cur)cur=rt,tmp=0;
    41             else tmp=dep[cur]+1,cur=son[cur][t[i]-'a'];
    42         }
    43         ret=max(ret,tmp);
    44     }
    45     return ret;
    46 }
    47 int main()
    48 {
    49     scanf("%s%s",s+1,t+1);
    50     lens=strlen(s+1);lent=strlen(t+1);
    51     printf("%d
    ",solve());
    52 }
  • 相关阅读:
    继承在WCF中的问题和解决办法
    bootstrap插件学习-bootstrap.dropdown.js
    C#山寨版本拨号客户端
    关于Certificate、Provisioning Profile、App ID的介绍及其之间的关系
    [源码]Literacy 快速反射读写对象属性,字段
    Hadoop Streaming框架学习(一)
    AOP详解
    SESSION会话技术
    mongodb 备份、还原、导入、导出
    Qt 技巧: 解决未解析的SSL问题
  • 原文地址:https://www.cnblogs.com/deadpool66/p/5989726.html
Copyright © 2011-2022 走看看