比起WC关于后缀数组的倍增法,要更有效率,由于模版使用的是指针,所以在new和delete处效率会有所消耗
来自NIT的后缀数组模版 注意在字符串间加入特殊符号进行区分 避免LCP越界
SAMLPE测试为HDU 1403~~
#include
<
iostream
>
#include < cmath >
#include < cstring >
using namespace std;
const int maxn = 210000 ;
char s[maxn];
int len,k;
int sa[maxn],rank[maxn],lcp[maxn];
int num[maxn];
inline bool leq( int a1, int a2, int b1, int b2)
{
return (a1 < b1 || a1 == b1 && a2 <= b2);
}
inline bool leq( int a1, int a2, int a3, int b1, int b2, int b3)
{
return (a1 < b1 || a1 == b1 && leq(a2, a3, b2, b3));
}
static void radixPass( int * a, int * b, int * r, int n, int K)
{
int * c = new int [K + 1 ];
int i,sum;
for (i = 0 ; i <= K; i ++ )
c[i] = 0 ;
for (i = 0 ; i < n; i ++ )
c[r[a[i]]] ++ ;
for (i = 0 , sum = 0 ; i <= K; i ++ )
{
int t = c[i];
c[i] = sum;
sum += t;
}
for (i = 0 ; i < n; i ++ )
b[c[r[a[i]]] ++ ] = a[i];
delete [] c;
}
void suffixArray( int * T, int * SA, int n, int K)
{
int n0 = (n + 2 ) / 3 , n1 = (n + 1 ) / 3 , n2 = n / 3 , n02 = n0 + n2;
int * R = new int [n02 + 3 ]; R[n02] = R[n02 + 1 ] = R[n02 + 2 ] = 0 ;
int * SA12 = new int [n02 + 3 ]; SA12[n02] = SA12[n02 + 1 ] = SA12[n02 + 2 ] = 0 ;
int * R0 = new int [n0];
int * SA0 = new int [n0];
int i,j;
for (i = 0 , j = 0 ; i < n + (n0 - n1); i ++ ) if (i % 3 != 0 ) R[j ++ ] = i;
radixPass(R , SA12, T + 2 , n02, K);
radixPass(SA12, R , T + 1 , n02, K);
radixPass(R , SA12, T , n02, K);
int name = 0 , c0 = - 1 , c1 = - 1 , c2 = - 1 ;
for ( i = 0 ; i < n02; i ++ )
{
if (T[SA12[i]] != c0 || T[SA12[i] + 1 ] != c1 || T[SA12[i] + 2 ] != c2)
{
name ++ ; c0 = T[SA12[i]]; c1 = T[SA12[i] + 1 ]; c2 = T[SA12[i] + 2 ];
}
if (SA12[i] % 3 == 1 ) { R[SA12[i] / 3 ] = name; }
else { R[SA12[i] / 3 + n0] = name; }
}
if (name < n02)
{
suffixArray(R, SA12, n02, name);
for ( int i = 0 ; i < n02; i ++ ) R[SA12[i]] = i + 1 ;
}
else
for ( int i = 0 ; i < n02; i ++ ) SA12[R[i] - 1 ] = i;
for (i = 0 , j = 0 ; i < n02; i ++ ) if (SA12[i] < n0) R0[j ++ ] = 3 * SA12[i];
radixPass(R0, SA0, T, n0, K);
for ( int p = 0 , t = n0 - n1, k = 0 ; k < n; k ++ )
{
#define GetI() (SA12[t] < n0 ? SA12[t] * 3 + 1 : (SA12[t] - n0) * 3 + 2)
int i = GetI();
int j = SA0[p];
if (SA12[t] < n0 ?
leq(T[i], R[SA12[t] + n0], T[j], R[j / 3 ]) : leq(T[i],T[i + 1 ],R[SA12[t] - n0 + 1 ], T[j],T[j + 1 ],R[j / 3 + n0]))
{
SA[k] = i; t ++ ;
if (t == n02)
for (k ++ ; p < n0; p ++ , k ++ ) SA[k] = SA0[p];
}
else {
SA[k] = j;
if ( ++ p == n0) for (k ++ ; t < n02; t ++ , k ++ ) SA[k] = GetI();
}
}
delete [] R; delete [] SA12; delete [] SA0; delete [] R0;
}
void LCP( char * str)
{
int i,j,k;
for (k = i = 0 ;i < len;i ++ )
{
if ( rank[i] == len - 1 ) lcp[ rank[i] ] = k = 0 ;
else
{
if ( k > 0 ) k -- ;
j = sa[ rank[i] + 1 ];
for (;str[i + k] == str[j + k];k ++ );
lcp[rank[i]] = k;
}
}
}
int main(){
int i, n;
scanf( " %s " ,s);
n = strlen(s);
s[n] = ' A ' - 1 ;
scanf( " %s " ,s + n + 1 );
len = strlen(s);
for (i = 0 ;i < len;i ++ )
num[i] = s[i] - ' A ' + 1 ;
suffixArray(num, sa, len, 60 );
for (i = 0 ;i < len;i ++ )
rank[sa[i]] = i;
LCP(s);
int ans = 0 ;
for (i = 1 ;i < len;i ++ )
if (sa[i] < n && sa[i - 1 ] > n || sa[i] > n && sa[i - 1 ] < n)
if (lcp[i - 1 ] > ans) ans = lcp[i - 1 ];
printf( " %d\n " ,ans);
return 0 ;
}
#include < cmath >
#include < cstring >
using namespace std;
const int maxn = 210000 ;
char s[maxn];
int len,k;
int sa[maxn],rank[maxn],lcp[maxn];
int num[maxn];
inline bool leq( int a1, int a2, int b1, int b2)
{
return (a1 < b1 || a1 == b1 && a2 <= b2);
}
inline bool leq( int a1, int a2, int a3, int b1, int b2, int b3)
{
return (a1 < b1 || a1 == b1 && leq(a2, a3, b2, b3));
}
static void radixPass( int * a, int * b, int * r, int n, int K)
{
int * c = new int [K + 1 ];
int i,sum;
for (i = 0 ; i <= K; i ++ )
c[i] = 0 ;
for (i = 0 ; i < n; i ++ )
c[r[a[i]]] ++ ;
for (i = 0 , sum = 0 ; i <= K; i ++ )
{
int t = c[i];
c[i] = sum;
sum += t;
}
for (i = 0 ; i < n; i ++ )
b[c[r[a[i]]] ++ ] = a[i];
delete [] c;
}
void suffixArray( int * T, int * SA, int n, int K)
{
int n0 = (n + 2 ) / 3 , n1 = (n + 1 ) / 3 , n2 = n / 3 , n02 = n0 + n2;
int * R = new int [n02 + 3 ]; R[n02] = R[n02 + 1 ] = R[n02 + 2 ] = 0 ;
int * SA12 = new int [n02 + 3 ]; SA12[n02] = SA12[n02 + 1 ] = SA12[n02 + 2 ] = 0 ;
int * R0 = new int [n0];
int * SA0 = new int [n0];
int i,j;
for (i = 0 , j = 0 ; i < n + (n0 - n1); i ++ ) if (i % 3 != 0 ) R[j ++ ] = i;
radixPass(R , SA12, T + 2 , n02, K);
radixPass(SA12, R , T + 1 , n02, K);
radixPass(R , SA12, T , n02, K);
int name = 0 , c0 = - 1 , c1 = - 1 , c2 = - 1 ;
for ( i = 0 ; i < n02; i ++ )
{
if (T[SA12[i]] != c0 || T[SA12[i] + 1 ] != c1 || T[SA12[i] + 2 ] != c2)
{
name ++ ; c0 = T[SA12[i]]; c1 = T[SA12[i] + 1 ]; c2 = T[SA12[i] + 2 ];
}
if (SA12[i] % 3 == 1 ) { R[SA12[i] / 3 ] = name; }
else { R[SA12[i] / 3 + n0] = name; }
}
if (name < n02)
{
suffixArray(R, SA12, n02, name);
for ( int i = 0 ; i < n02; i ++ ) R[SA12[i]] = i + 1 ;
}
else
for ( int i = 0 ; i < n02; i ++ ) SA12[R[i] - 1 ] = i;
for (i = 0 , j = 0 ; i < n02; i ++ ) if (SA12[i] < n0) R0[j ++ ] = 3 * SA12[i];
radixPass(R0, SA0, T, n0, K);
for ( int p = 0 , t = n0 - n1, k = 0 ; k < n; k ++ )
{
#define GetI() (SA12[t] < n0 ? SA12[t] * 3 + 1 : (SA12[t] - n0) * 3 + 2)
int i = GetI();
int j = SA0[p];
if (SA12[t] < n0 ?
leq(T[i], R[SA12[t] + n0], T[j], R[j / 3 ]) : leq(T[i],T[i + 1 ],R[SA12[t] - n0 + 1 ], T[j],T[j + 1 ],R[j / 3 + n0]))
{
SA[k] = i; t ++ ;
if (t == n02)
for (k ++ ; p < n0; p ++ , k ++ ) SA[k] = SA0[p];
}
else {
SA[k] = j;
if ( ++ p == n0) for (k ++ ; t < n02; t ++ , k ++ ) SA[k] = GetI();
}
}
delete [] R; delete [] SA12; delete [] SA0; delete [] R0;
}
void LCP( char * str)
{
int i,j,k;
for (k = i = 0 ;i < len;i ++ )
{
if ( rank[i] == len - 1 ) lcp[ rank[i] ] = k = 0 ;
else
{
if ( k > 0 ) k -- ;
j = sa[ rank[i] + 1 ];
for (;str[i + k] == str[j + k];k ++ );
lcp[rank[i]] = k;
}
}
}
int main(){
int i, n;
scanf( " %s " ,s);
n = strlen(s);
s[n] = ' A ' - 1 ;
scanf( " %s " ,s + n + 1 );
len = strlen(s);
for (i = 0 ;i < len;i ++ )
num[i] = s[i] - ' A ' + 1 ;
suffixArray(num, sa, len, 60 );
for (i = 0 ;i < len;i ++ )
rank[sa[i]] = i;
LCP(s);
int ans = 0 ;
for (i = 1 ;i < len;i ++ )
if (sa[i] < n && sa[i - 1 ] > n || sa[i] > n && sa[i - 1 ] < n)
if (lcp[i - 1 ] > ans) ans = lcp[i - 1 ];
printf( " %d\n " ,ans);
return 0 ;
}