HDU 1403 字符串 后缀数组 只能说勉强会用后缀数组了

来源:互联网 发布:人工智能对话app 编辑:程序博客网 时间:2024/06/06 04:49

Longest Common Substring

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


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
bananacianaic
 

Sample Output
3
 

Author
Ignatius.L
 

关于后缀数组。请详细看这里  http://blog.csdn.net/jokes000/article/details/7839686

后缀数组套用模板。直接计算出suffix(i)的排序,然后调用height数组计算字符串最大的相同。

最后计算时,因为height[i]=height[sa[i]] 跟 height[sa[i]-1] 的公共前缀的数目 ,需要通过sa[i-1]跟sa[i]判断是否来自于不同的字符串。通过中间len(第一个字符串当中间值来比较)

/* * @author ipqhjjybj * @date  20130707 * */#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>using namespace std;#define clr(x) memset(x,0,sizeof(x))#define MAXN 200003int cmp(int *r,int a,int b,int l){    return r[a]==r[b]&&r[a+l]==r[b+l];}int wa[MAXN],wb[MAXN],wv[MAXN],wss[MAXN];//call da(s,sa,len,300) 来计算,300这个值有点太大了。只需要大于最大的字符的ASCII值即可void da(char *r,int *sa,int n,int m){    //后缀数组sa:将s的n个后缀从小到大排序后将    //排序后的后缀的开头位置 顺次放入sa中,    //则sa[i]储存的是排第i大的后缀的开头位置。    //简单的记忆就是“排第几的是谁”。    clr(wa),clr(wb),clr(wv),clr(wss);//是x排序,wb是y排序,wss基数排序,wv只是暂时存储    int i,j,p,*x=wa,*y=wb,*t;    for(i=0;i<m;i++)wss[i]=0;//初始化,wss[i]表示i字面值的数的个数    for(i=0;i<n;i++)wss[x[i]=r[i]]++;//x指代wa , 计数排序。如果数据过大则采用快速排序    for(i=1;i<m;i++)wss[i]+=wss[i-1];//加上排前面的数目,就是目前的排序位置    for(i=n-1;i>=0;i--)sa[--wss[x[i]]]=i;//这里最好不要写成i=0,你可以试着打印aaaa排序后的结果看下    for(j=1,p=1;p<n;j<<=1,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]]; //wv就是每次暂时存储的功能。        for(i=0;i<m;i++)wss[i]=0;//又是一轮基数排序        for(i=0;i<n;i++)wss[wv[i]]++;        for(i=1;i<m;i++)wss[i]+=wss[i-1];        for(i=n-1;i>=0;i--)sa[--wss[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;}int rank[MAXN],height[MAXN];//h[i]=height[rank[i]]//h[i]≥h[i-1]-1void calheight(char *r,int *sa,int n){    int i,j,k;    clr(rank),clr(height);    for(i=1;i<n;i++)rank[sa[i]]=i;    for(k=i=0;i<n;height[rank[i++]]=k)        for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++)            ;    return;}char s[MAXN];int sa[MAXN];int main(){    int len1,len2,i,j,ans;    //freopen("1403.in","r",stdin);    while(scanf("%s",s)!=EOF){        s[len1=strlen(s)]='#';        scanf("%s",s+len1+1);        len2=strlen(s);        da(s,sa,len2,300);        calheight(s,sa,len2);        ans=0;        for(i=1;i<len2;i++){            if(height[i]>ans)                if((sa[i-1]<(len1)&&sa[i]>(len1))||                   (sa[i]<(len1)&&sa[i-1]>(len1)))                   ans=height[i];        }        printf("%d\n",ans);    }    return 0;}

勉强会用模板了。。

原创粉丝点击