HDU 1403 Longest Common Substring(最长公共前缀)

Posted 谦谦君子,陌上其华

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 1403 Longest Common Substring(最长公共前缀)相关的知识,希望对你有一定的参考价值。

http://acm.hdu.edu.cn/showproblem.php?pid=1403

题意:
给出两个字符串,求最长公共子串的长度。

 

思路:

刚开始学后缀数组,确实感觉很难,但是这东西很强大,所以必须要学会它,推荐罗穗骞大牛的论文。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<vector>
 6 #include<stack>
 7 #include<queue>
 8 #include<cmath>
 9 #include<map>
10 #include<set>
11 using namespace std;
12 typedef long long ll;
13 typedef pair<int,int> pll;
14 const int INF = 0x3f3f3f3f;
15 const int maxn=200000+5;
16 
17 char s[maxn],s1[maxn];
18 int sa[maxn],t[maxn],t2[maxn],c[maxn],n;
19 int Rank[maxn],height[maxn];
20 
21 void build_sa(int m)
22 {
23     int *x=t,*y=t2;
24     //基数排序
25     for(int i=0;i<m;i++)    c[i]=0;
26     for(int i=0;i<n;i++)    c[x[i]=s[i]]++;
27     for(int i=1;i<m;i++)    c[i]+=c[i-1];
28     for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
29     for(int k=1;k<=n;k<<=1)
30     {
31         int p=0;
32         //直接利用sa数组排序第二关键字
33         for(int i=n-k;i<n;i++)  y[p++]=i;
34         for(int i=0;i<n;i++)    if(sa[i]>=k)    y[p++]=sa[i]-k;
35         //基数排序第一关键字
36         for(int i=0;i<m;i++)    c[i]=0;
37         for(int i=0;i<n;i++)    c[x[y[i]]]++;
38         for(int i=1;i<m;i++)    c[i]+=c[i-1];
39         for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
40         //根据sa和y计算新的x数组
41         swap(x,y);
42         p=1;
43         x[sa[0]]=0;
44         for(int i=1;i<n;i++)
45             x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
46         if(p>=n)
47             break;
48         m=p;                //下次基数排序的最大值
49     }
50 }
51 
52 void getHeight()
53 {
54     int i,j,k=0;
55     for(i=1;i<=n;i++)  Rank[sa[i]]=i;
56     for(i=0;i<n;i++)
57     {
58         if(k)  k--;
59         int j=sa[Rank[i]-1];
60         while(s[i+k]==s[j+k])  k++;
61         height[Rank[i]]=k;
62     }
63 }
64 
65 int main()
66 {
67     //freopen("in.txt","r",stdin);
68     while(~scanf("%s",s))
69     {
70         int len = strlen(s);
71         s[len]=0;
72         scanf("%s",s+len+1);
73         n=strlen(s);
74         build_sa(128);
75         getHeight();
76         int ans=0;
77         for(int i=1;i<n;i++)
78         {
79             if(height[i]>ans)
80             {
81                 if((sa[i]>len && sa[i-1]<len) || (sa[i]<len && sa[i-1]>len))
82                     ans=height[i];
83             }
84         }
85         printf("%d\n",ans);
86     }
87     return 0;
88 }

 

以上是关于HDU 1403 Longest Common Substring(最长公共前缀)的主要内容,如果未能解决你的问题,请参考以下文章

HDU1403Longest Common Substring

HDU 1403 Longest Common Substring(最长公共前缀)

[HDU1403]Longest Common Substring(后缀数组)

HDU-1403-Longest Common Substring(后缀数组的高度数组运用)

SPOJ 1812 Longest Common Substring II

Longest Common Substring(最长公共子序列)