您的位置:首页 > 其它

HDU1403 - Longest Common Substring(后缀数组求nlog(n)的最长公共子序列)

2014-12-18 10:49 399 查看
题目链接:HDU1403

【题意】给出两个长度<=100000的字符串,求他们的最长公共子序列。

【分析】最长公共子序列以前学过可以用DP求,但是复杂度是n^2的,这题显然不能用;学后缀数组时看到这题,把两个字符串链接起来中间加上一个特殊字符分隔,求出height数组,则枚举height数组时限制一下在两个串,求最大值即可。

【AC CODE】140ms

#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <map>
//#include <unordered_map>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
typedef long long LL;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
const int INF = 0x3f3f3f3f, MAXN = 100000*2+10;
struct DA{
int s[MAXN];
int sa[MAXN],t[MAXN], t2[MAXN], c[MAXN],n;
void bulid_sa(int m)
{
int *x = t, *y = t2,p;
memset(c,0,sizeof(int)*m);
rep(i,0,n) c[x[i] = s[i]]++;
rep(i,1,m) c[i] += c[i-1];
per(i,n-1,0) sa[--c[x[i]]] = i;
for(int k = 1; k <= n; k <<= 1, m = p)
{
p = 0;
rep(i,n-k,n) y[p++] = i;
rep(i,0,n) if(sa[i] >= k) y[p++] = sa[i]-k;
memset(c,0,sizeof(int)*m);
rep(i,0,n) c[x[y[i]]]++;
rep(i,1,m) c[i] += c[i-1];
per(i,n-1,0) sa[--c[x[y[i]]]] = y[i];
swap(x,y);
p = 1;x[sa[0]] = 0;
rep(i,1,n) x[sa[i]] = y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k] == y[sa[i]+k]?p-1:p++;
if(p>=n) break;
}
}
int rank[MAXN], height[MAXN];
void get_height()
{
int k = 0;
rep(i,0,n) rank[sa[i]] = i;
rep(i,0,n)
{
if(k) k--;
int j = sa[rank[i]-1];
while(s[i+k] == s[j+k]) k++;
height[rank[i]] = k;
}
}
void add(int ch)
{
s[n++] = ch-'a'+1;
}
}da;
char a[MAXN],b[MAXN];

int main()
{
#ifdef SHY
freopen("e:\\1.txt", "r", stdin);
#endif
while(~scanf("%s%s", a,b))
{
da.n = 0;
char *p = a;
while(*p)
{
da.add(*p);
p++;
}
da.add(26+'a');
int len = da.n;
p = b;
while(*p)
{
da.add(*p);
p++;
}
//da.add(27+'a');
da.add('a'-1);
da.bulid_sa(28);
da.get_height();
int ans = 0;
repe(i,2,da.n)
{
if((da.sa[i] < len && da.sa[i-1] >= len) || (da.sa[i] >= len && da.sa[i-1] < len))
{
ans = max(ans,da.height[i]);
}
}
printf("%d\n", ans);
}
return 0;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  后缀数组