您的位置:首页 > 其它

CF 427D 后缀数组

2016-03-05 18:17 281 查看
大意是寻找两个字符串中最短的公共子串,要求子串在两个串中都是唯一的。

造一个S#T的串,做后缀数组,从小到大枚举子串长度在height数组中扫描,如果某一个组中来自两个串的数量分别为1,就找到了答案。

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctime>
#include <numeric>
#include <cassert>

using namespace std;

const int N=10005;;

char s
;

struct SuffixArray {
int wa
, wb
, cnt
, wv
;
int rk
, height
;
int sa
;
bool cmp(int r[], int a, int b, int l) {
return r[a] == r[b] && r[a+l] == r[b+l];
}
void calcSA(char r[], int n, int m) {
int i, j, p, *x = wa, *y = wb;
for (i = 0; i < m; ++i) cnt[i] = 0;
for (i = 0; i < n; ++i) cnt[x[i]=r[i]]++;
for (i = 1; i < m; ++i) cnt[i] += cnt[i-1];
for (i = n-1; i >= 0; --i) sa[--cnt[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) cnt[i] = 0;
for (i = 0; i < n; ++i) cnt[wv[i]]++;
for (i = 1; i < m; ++i) cnt[i] += cnt[i-1];
for (i = n-1; i >= 0; --i) sa[--cnt[wv[i]]] = y[i];
for (swap(x, y), 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 calcHeight(char r[], int n) {
int i, j, k = 0;
for (i = 0; i <= n; ++i) rk[sa[i]] = i;
for (i = 0; i < n; height[rk[i++]] = k)
for (k?k--:0, j = sa[rk[i]-1]; r[i+k] == r[j+k]; k++);
}
bool solve(int k,int n,int div) {
int ca=0,cb=0;
for (int i=1;i<=n;i++) {
if (height[i]<k) {
if (ca==1&&cb==1)
return true;
ca=0;cb=0;
if (sa[i]<div) ca++;
else if (sa[i]>div) cb++;
continue;
}
if (sa[i]<div) ca++;
else if (sa[i]>div) cb++;
}
return ca==1&&cb==1;
}
}suf;

char a
,b
;

int main(){
scanf("%s %s",a,b);
int n=strlen(a),m=strlen(b);
strcpy(s,a);
s
='#';
strcpy(s+n+1,b);
int tot=n+m+1;
suf.calcSA(s,tot+1,128);
suf.calcHeight(s,tot);
int ret=-1;
for (int i=1;i<=n;i++) {
if (suf.solve(i,tot,n)) {
ret=i;
break;
}
}
printf("%d\n",ret);
return 0;
}


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