您的位置:首页 > 其它

Poj 2774 Long Long Message (后缀数组)

2015-09-04 17:19 204 查看
题目链接:

  Poj 2774 Long Long Message

题目描述:

  给出A,B两个字符串,求最长公共子串?

解题思路:

  求A,B字符串的最长公共子串可以转化为求A,B字符串后缀数组的最长公共前缀。把B串连接在A串后面,用'$'隔开组成r串。求出r串的height数组,最大的height[i](满足sa[i]与sa[i-1]不在同一文本串中)就是答案。时间复杂度大概为O((|A|+|B|)*log(|A|+|B|))。(阅兵假期用来搞这个,感觉还是有点怪怪的感觉,不过秉承着以前的学习风格,先记下模板,以后在水题中慢慢体会好了)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 200010;

int sa[maxn], rank[maxn], height[maxn];
int t1[maxn], t2[maxn], r[maxn], c[maxn];
bool cmp (int *str, int a, int b, int k)
{//rank相邻的两个串,第一第二关键字都一样,rank一样
return str[a]==str[b] && str[a+k]==str[b+k];
}
int da (int *str, int n, int m)
{
int *x = t1, *y = t2, i, j;
n ++;
//基数排序,
for (i=0; i<m; i++) c[i] = 0;
for (i=0; i<n; i++) c[x[i] = str[i]] ++;
for (i=1; i<m; i++) c[i] += c[i-1];
for (i=n-1; i>=0; i--) sa[-- c[str[i]]] = i;
for (j=1; j<=n; j*=2)
{
//用sa数组对第二关键字排序
int p = 0;
for (i=n-j; i<n; i++) y[p++] = i;  //不能添加长度为j的串,第二关键字附为最小
for (i=0; i<n; i++) if (sa[i] >= j) y[p++] = sa[i] - j;
//枚举rank,起点大于j的串,才能倍增
//更新sa数组
for (i=0; i<m; i++) c[i] = 0;
for (i=0; i<n; i++) c[x[y[i]]] ++;
for (i=1; i<m; i++) c[i] += c[i-1];
for (i=n-1; i>=0; i--) sa[-- c[x[y[i]]]] = y[i];
//更新x数组
swap (x, y);
p = 1, x[sa[0]] = 0;
for (i=1; i<n; i++)
x[sa[i]] = cmp(y, sa[i-1], sa[i], j)?p-1:p++;
if (p >= n)
break;
m = p;
}
//计算rank数组
for (i=0; i<n; i++)
rank[sa[i]] = i;
//计算height数组
n --;
int k = 0;
for (i=0; i<n; i++)
{//枚举起点, height[名次]
if (k)  k --;
j = sa[rank[i]-1];
while (str[i+k]==str[j+k])    k++;
height[rank[i]] = k;
}
}
int main ()
{
char str1[maxn/2], str2[maxn/2];
while (scanf ("%s %s", str1, str2) != EOF)
{
int n1 = strlen(str1);
int n2 = strlen(str2);
int n = n1 + n2 + 1;
for (int i=0; i<n; i++)
{
if (i < n1)
r[i] = str1[i];
else if (i == n1)
r[i] = '$';
else
r[i] = str2[i-n1-1];
}
r
= 0;
da (r, n, 128);
int ans = 0;
for (int i=1; i<n; i++)
{//i为rank
if (sa[i]<n1&&sa[i-1]>n1 || sa[i]>n1&&sa[i-1]<n1)
//rank相邻的后缀串不在同一个字符串
ans = max(ans, height[i]);
}
printf ("%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: