您的位置:首页 > 其它

POJ2774 后缀数组,求两个字符串的最长公共子串

2016-10-18 23:16 525 查看
1 学习别人的模板

2 列出两种情况

(1)代码一是两个字符串的最长公共子串poj2774

(2)代码二是假设求多个字符串中某两个字符串的最长公共子串

其中(2)没有题目,自己编的,为了便于重点理解:字符串组合时中间插入的字符对应的数应该是与输入的字符对应的ASC码不一样的数字,所以如果进行多个字符串的组合而插入多个间隔字符,那这些间隔字符应该也互相不同。

(

①代码一中 fir[k++]=31,对应代码二中 r[k++]=bian++;   数组名无所谓、注意的改变是31变为bian++。

②代码一中 da(r,k+1,31),对应代码二中 GetSa(r,k+1,bian);   函数名无所谓、注意的改变是31变为bian

)

3

注意,len是字符串实际长度(不补0的情况下):sa[],下标是该后缀的名次(1到len),值是该后缀的首字符在字符串中的位置(0到len-1);rank_[],下标是该后缀首字符在字符串中的位置(0到len-1),值是该后缀的名次(1到len);heigh[],下标是该后缀的名次(1到len),值是sa[i]与sa[i-1]的公共前缀长度,且heigh[1]是第一名次的后缀与第零名次后缀的公共前缀长度,因为第零名次后缀不存在所以heigh[1]也没有意义。

4

除了拿出来的几个函数,注意代入函数的语句:

da(r,k+1,31);//注意K+1
calHeight(r,k);


5

代码一:

#include<iostream>
#include<cstring>
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
const int MAX = 200050;
char fir[MAX],sec[MAX];
int sa[MAX], rank[MAX], height[MAX];
int wa[MAX], wb[MAX], wv[MAX], wd[MAX];

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) // 倍增算法0(nlgn)。
{
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 = 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 ++) 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) // 求height数组。
{
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 ++);
}
}
int main()
{
int r[MAX];
int len1,len2,k,maxx;
while(~scanf("%s %s",fir,sec)){
len1=strlen(fir);
len2=strlen(sec);
k=0;
maxx=0;
for(int i=0;i<len1;i++) r[k++]=fir[i]-'a'+1;
fir[k++]=31;
for(int i=0;i<len2;i++) r[k++]=sec[i]-'a'+1;
sec[k]=0;

da(r,k+1,31);//注意K+1 calHeight(r,k);
for(int i=2;i<k;i++){
if(height[i]>maxx){
if((sa[i-1]<len1&&sa[i]>len1)||(sa[i]<len1&&sa[i-1]>len1))
maxx=height[i];
}
}
cout<<maxx<<endl;
}
return 0;
}

6

代码二

input::

3

aabbaabb

abbababb

bbbbbabb

0

output::

4

abba

#include<iostream>
#include<cstring>
#include <stdio.h>
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;

//r[] 下标是字符位置从0开始;s[] 下标是名次从1开始、值是首字符位置从0开始;heigh[] 下标是名次从1开始、值是第i个名次的后缀和第i-1个名次的后缀的最长公共前缀长度(且heigh[1]没有意义);rank[] 下标是首字符位置从0开始、值是名次从1开始。
const int MAX = 800050;
char fir[MAX];
char scan[MAX];
int r[MAX];
int len[5000];
int sa[MAX], rank[MAX], height[MAX];
int wa[MAX], wb[MAX], wv[MAX], wd[MAX];
int cmp(int *r, int a, int b, int l)
{
return r[a] == r[b] && r[a+l] == r[b+l];
}
void GetSa(int *r, int n, int m) // 倍增算法0(nlgn)。
{
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 = 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 ++) 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 GetHeight(int *r, int n) // 求height数组。
{
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 ++);
}
}
int main()
{
int t;

while(~scanf("%d",&t)&&t){
int k=0;
int len_k=0;
int bian=30;
char com;
char temp=getchar();
for(int i=1;i<=t;i++){
while(scanf("%c",&com)){
if(com!='\n') r[k++]=com-'a'+1;
else {
r[k++]=bian++;
len[len_k++]=k-1;
break;
}
}
}
fir[k]=0;
GetSa(r,k+1,bian);
GetHeight(r,k);
int maxx=0;
int tem=0;
for(int i=2;i<k;i++){
if(height[i]>maxx){
for(int j=0;j<len_k;j++){
if((sa[i]>len[j]&&sa[i-1]<len[j])||(sa[i-1]>len[j]&&sa[i]<len[j])){
maxx=height[i];
tem=i;
}
}
}
}
cout<<maxx<<endl;
cout<<sa[tem]<<endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐