HDU1403 Longest Common Substring(最長公共子串、後綴數組入門)

題目鏈接:點擊打開題目鏈接

Longest Common Substring

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5417    Accepted Submission(s): 1923


Problem Description
Given two strings, you have to tell the length of the Longest Common Substring of them.

For example:
str1 = banana
str2 = cianaic

So the Longest Common Substring is "ana", and the length is 3.
 

Input
The input contains several test cases. Each test case contains two strings, each string will have at most 100000 characters. All the characters are in lower-case.

Process to the end of file.
 

Output
For each test case, you have to tell the length of the Longest Common Substring of them.
 

Sample Input
banana cianaic
 

Sample Output
3
 

Author
Ignatius.L

題意:給兩個字符串,求最長公共子串的長度
方法將它們合併爲一個串,然後利用後綴數組求解;先輸入一個串s,長度len1,再輸入第二個串scanf("%s,s+len1),這樣就把兩個串合併到了一起,這時長度len,把字符型數組s轉換爲整型數組r,再加一個r[len]=0;這時候再套用後綴數組的模板,求出height[i]的最大值,但是要保證相鄰的兩個子串的sa分別屬於原來輸入的兩個串,即要滿足sa[i-1]<=len1 && sa[i]>len1或者sa[i]<=len1&&sa[i-1]>len1;
貼AC代碼:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;
int wa[200005],wb[200005],wv[200005],ws[200005];
int r[200005],height[200005],rank1[200005],sa[200005];char s[200005];
int cmp(int *r,int a,int b,int l){
    return r[a]==r[b]&&r[a+l]==r[b+l];
}
void da(int *r,int *sa,int n,int m){
    int i,j,p,*x=wa,*y=wb,*t;
    for(i=0;i<m;i++) ws[i]=0;
    for(i=0;i<n;i++) ws[x[i]=r[i]]++;
    for(i=1;i<m;i++) ws[i]+=ws[i-1];
    for(i=n-1;i>=0;i--) sa[--ws[x[i]]]=i;
    for(j=1,p=1;p<n;j*=2,m=p){
        for(p=0,i=n-j;i<n;i++) y[p++]=i;
        for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
        for(i=0;i<n;i++) wv[i]=x[y[i]];
        for(i=0;i<m;i++) ws[i]=0;
        for(i=0;i<n;i++) ws[wv[i]]++;
        for(i=1;i<m;i++) ws[i]+=ws[i-1];
        for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];
        for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
            x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    }
    return;
}
void calheight(int *r,int *sa,int n){
    int i,j,k=0;
    for(i=1;i<=n;i++) rank1[sa[i]]=i;
    for(i=0;i<n;height[rank1[i++]]=k)
        for(k?k--:0,j=sa[rank1[i]-1];r[i+k]==r[j+k];k++);
    return;
}
int main()
{
    int i;
    while(scanf("%s",s)!=EOF)
    {
        int len=strlen(s),len1=strlen(s);
        scanf("%s",s+len);
        len=strlen(s);
        for(i=0;i<len;i++)
        r[i]=s[i];
        r[len]=0;
        da(r,sa,len+1,300);
        calheight(r,sa,len);
        int max=0;
        for(i=1;i<=len;i++)
        {
            if(height[i]>max)
            {
                if(sa[i-1]<len1&&sa[i]>=len1||sa[i-1]>=len1&&sa[i]<len1)
                max=height[i];
            }
        }
        printf("%d\n",max);

    }
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章