Poj 2774两个字符串的最长公共子串长度



给A ,B 两个串 

要求两个字符串的最长公共子串长度


只需要用'$',分割一下就好了,不能用0

A$B


#include<iostream>
#include<string.h>
#include<cstdio>
#include<cstring>
#define MIN(a,b) (a)>(b)?(b):(a)
#define MAX(a,b) (a)>(b)?(a):(b)
#define INF 0x3f3f3f
using namespace std;

const int M=200010;

int N,alen,blen;

int str[M];
char a[M>>1],b[M>>1];


int sa[M] , rank[M] , height[M];  
int wa[M] , wb[M] , wv[M] , wd[M];  
  
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 n , int m)  
{  
    int i , j , p , *x = wa , *y = wb , *t;  
    for (i = 0 ; i < m ; i++)wd[i] = 0;  
    for (i = 0 ; i < n ; i++)wd[x[i]=r[i]]++;  
    for (i = 1 ; i < m ; i++)wd[i] += wd[i-1];  
    for (i = n-1 ; i >= 0 ; i--) sa[--wd[x[i]]] = i;  
    for (j = 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++)wd[i] = 0;  
        for (i = 0 ; i < n ; i++)wd[wv[i]]++;  
        for (i = 1 ; i < m ; i++)wd[i] += wd[i-1];  
        for (i = n-1 ; i >= 0 ; i--)sa[--wd[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++;  
    }  
}  
  
void calheight(int *r , int n)  
{  
    int i , j , k = 0;  
    for (i = 1 ; i <= n ; i++) rank[sa[i]] = i;  
    for (i = 0 ; i < n ; height[rank[i++]] = k)  
    for (k?k--:0,j = sa[rank[i]-1] ; r[i+k] == r[j+k] ; k++);  //若分割符为0则有可能会和B串末尾0配 导致h多加1
}  


int main()
{
	
		int i,j;
		memset(str,0,sizeof(str));
        scanf("%s",a);
		alen=strlen(a);
		for(i=0;i<alen;i++)
			str[i]=a[i]-'a'+2;  //保证为正数且比'$'大
		str[alen]=1; //此处'$'
		scanf("%s",b);
		blen=strlen(b);
		for(i=alen+1,j=0;j<blen;j++,i++)
			str[i]=b[j]-'a'+2;
		int minlen=MIN(alen,blen);
		int len=alen+blen;
		da(str,len+1,30);  
        calheight(str,len);
        int ans =0;
		for (i =1; i <= len+1 ; i++)
			if ((sa[i] < alen && sa[i -1] > alen) || (sa[i] > alen && sa[i -1] < alen))//保证一个在A 一个在B
				if (height[i] > ans)
					ans = height[i];
		printf("%d\n",ans);
	return 0;
}


你可能感兴趣的:(后缀数组)