2.1 最长公共前缀
height 数组:定义height【i】=suffix(sa【i-1】)和suffix(sa【i】)的最长公共前缀;也就是排名相邻的两个后缀的最长公共前缀。
那么对于j和k,不妨设rank【j】<rank【k】;不妨设rank【j】<rank【k】,则有以下性质:
suffix(j)和suffix(k)的最长公共前缀为height【rank【j】+1】到height【rank【k】】中的最小值;
定义好h【i】=height[rank[i]],也就是suffix(i)和在它前一名的后缀的最长公共前缀;
h数组有以下性质:
h【i】》=h【i-1】-1;
求公共子串
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
#define rep(i,n) for(int i = 0;i < n; i++)
const int maxn = 200000+66;
int rk[maxn],sa[maxn],height[maxn],w[maxn],wa[maxn],res[maxn];
void getSa (int len,int up) {
int *k = rk,*id = height,*r = res, *cnt = wa;
rep(i,up) cnt[i] = 0;
rep(i,len) cnt[k[i] = w[i]]++;
rep(i,up) cnt[i+1] += cnt[i];
for(int i = len - 1; i >= 0; i--) {
sa[--cnt[k[i]]] = i;
}
int d = 1,p = 0;
while(p < len){
for(int i = len - d; i < len; i++)
id[p++] = i;
rep(i,len)
if(sa[i] >= d)
id[p++] = sa[i] - d;
rep(i,len) r[i] = k[id[i]];
rep(i,up) cnt[i] = 0;
rep(i,len) cnt[r[i]]++;
rep(i,up) cnt[i+1] += cnt[i];
for(int i = len - 1; i >= 0; i--) {
sa[--cnt[r[i]]] = id[i];
}
swap(k,r);
p = 0;
k[sa[0]] = p++;
rep(i,len-1) {
if(sa[i]+d < len && sa[i+1]+d <len &&r[sa[i]] == r[sa[i+1]]&& r[sa[i]+d] == r[sa[i+1]+d])
k[sa[i+1]] = p - 1;
else k[sa[i+1]] = p++;
}
if(p >= len) return ;
d *= 2,up = p, p = 0;
}
}
int ans=0;
void getHeight(int len) {
rep(i,len) rk[sa[i]] = i;
height[0] = 0;
for(int i = 0,p = 0; i < len - 1; i++) {
int j = sa[rk[i]-1];
while(i+p < len&& j+p < len&& w[i+p] == w[j+p]) {
p++;
}
height[rk[i]] = p;
p = max(0,p - 1);
}
}
int getSuffix(char s[]) {
int len = strlen(s),up = 0;
for(int i = 0; i < len; i++) {
w[i] = s[i];
up = max(up,w[i]);
}
w[len++] = 0;
getSa(len,up+1);
getHeight(len);
return len;
}
int main()
{
char s1[maxn];
scanf("%s",s1);
int t=strlen(s1);
s1[t]='0';
scanf("%s",s1+t+1);
getSuffix(s1);
int t1=strlen(s1);
int ans=0;
for(int i=0;i<t1;i++)
{
if(height[i]>ans)
{
if((sa[i]<t&&sa[i-1]>t)||(sa[i]>t&&sa[i-1]<t))
ans=height[i];
}
}
printf("%d",ans);
return 0;
}