zoukankan      html  css  js  c++  java
  • 后缀数组练习3:连续重复子串

    比前面两个练习题更加简单,只要知道height数组的性质就可以了

    1469: 后缀数组3:连续重复子串

    poj2774

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 101  解决: 57
    [提交] [状态] [讨论版] [命题人:admin]

    题目描述

    【问题描述】

    求两个字符串的最长公共子串。(长度不超过100000,都是小写字母)

    【样例】
    输入:

    yeshowmuchiloveyoumydearmotherreallyicannotbelieveit

    yeaphowmuchiloveyoumydearmother
    输出:

    27 

    不多说,这道题的思路我会引用罗穗骞大佬的论文当中的讲解

    简单来说,就是把两个字符串合并,然后用get_he找到他们的最长重复子串,但是要判断是sa是分别属于两个不同的子串里面的

    代码实现

     1 /*先用个分隔符将两个字符串连接起来,再用后缀数组求出height数组的值,
     2 找出一个height值最大并且i与i-1的sa值分别在两串字符中就好*/
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<algorithm>
     7 #include<cmath>
     8 #include<iostream>
     9 using namespace std;
    10 int sa[200020],Rank[200020],rsort[200020];
    11 int cnt[200020],pos[200020],height[200020];
    12 bool cmp(int x,int y,int k){return cnt[x]==cnt[y] && cnt[x+k]==cnt[y+k];}
    13 char a[200020],b[200020];
    14 void get_sa(int n,int m) 
    15 {
    16     int k=1,p=0,len;
    17     for(int i=1;i<=n;i++) Rank[i]=a[i];
    18     memset(rsort,0,sizeof(rsort));
    19     for(int i=1;i<=n;i++) rsort[Rank[i]]++;
    20     for(int i=1;i<=m;i++) rsort[i]+=rsort[i-1];
    21     for(int i=n;i>=1;i--) sa[rsort[Rank[i]]--]=i;
    22     for(int k=1;k<n;k<<=1)
    23     {
    24         len=0;
    25         for(int i=n-k+1;i<=n;i++) pos[++len]=i;
    26         for(int i=1;i<=n;i++) if(sa[i]>k) pos[++len]=sa[i]-k;
    27         for(int i=1;i<=n;i++) cnt[i]=Rank[pos[i]];
    28         memset(rsort,0,sizeof(rsort));
    29         for(int i=1;i<=n;i++) rsort[cnt[i]]++;
    30         for(int i=1;i<=m;i++) rsort[i]+=rsort[i-1];
    31         for(int i=n;i>=1;i--) sa[rsort[cnt[i]]--]=pos[i];
    32         for(int i=1;i<=n;i++) cnt[i]=Rank[i];
    33         p=1; Rank[sa[1]]=1;
    34         for(int i=2;i<=n;i++)
    35         {
    36             if(!cmp(sa[i],sa[i-1],k)) p++;
    37             Rank[sa[i]]=p;
    38         }
    39         m=p;
    40     }
    41     a[0]=0; sa[0]=0;
    42 }
    43 void get_he(int n)
    44 {
    45     int j,k=0;
    46     for(int i=1;i<=n;i++)
    47     {
    48         j=sa[Rank[i]-1];
    49         if(k) k--;
    50         while(a[j+k]==a[i+k]) k++;
    51         height[Rank[i]]=k;
    52     }
    53 }
    54 int main()
    55 {
    56     scanf("%s",a+1); scanf("%s",b+1);
    57     int n=strlen(a+1),m=strlen(b+1);
    58     a[n+1]='T';/*分隔符*/
    59     for(int i=n+2;i<=n+m+1;i++) a[i]=b[i-n-1];/*目前总长度为n+m+1,合并字符串的操作*/
    60     get_sa(n+m+1,256); get_he(n+m+1);/*一串的ASCII码为128,两串就是256*/
    61     int ans=0;
    62     for(int i=2;i<=n+m+1;i++)
    63         if((sa[i-1]<=n && sa[i]>n+1) || (sa[i-1]>n+1 && sa[i]<=n))/*保证sa分别在两串当中*/
    64             ans=max(ans,height[i]);/*更新最大值*/
    65     printf("%d
    ",ans);
    66     return 0;
    67 }
    Tristan Code
  • 相关阅读:
    【数论】【快速幂】【扩展欧几里得】【BSGS算法】bzoj2242 [SDOI2011]计算器
    【数论】【ex-BSGS】poj3243 Clever Y
    【数论】【扩展欧几里得】hdu3579 Hello Kiki
    【CCpp程序设计2017】推箱子游戏
    【Miller-Rabin算法】
    【数论】nefu119 组合素数
    【数论】nefu118 n!后面有多少个0
    【树形dp】vijos P1180 选课
    【树形dp】Codeforces Round #405 (rated, Div. 1, based on VK Cup 2017 Round 1) B. Bear and Tree Jumps
    【树形dp】VK Cup 2012 Round 1 D. Distance in Tree
  • 原文地址:https://www.cnblogs.com/Tristanjiang/p/11381930.html
Copyright © 2011-2022 走看看