pku3450 Corporate Identity

 

思路:以第一个串为基串,将另外N-1个串分别与基串拼接跑后缀数组,记录基串每一个位置与另外一个串的最长匹配长度,求出每一个位置在和别的所有串跑后缀数组时所得的最长匹配中的最小值,最后求出所有位置中的最大值就是所求。

也可以用类似Music Theme的二分枚举搞掉,但是代码太丑陋所以就不贴啦

/*
Memory: 428K  Time: 188MS 
Language: C++  Result: Accepted 
*/

#include 
< iostream >
using   namespace  std;

#define  MAXN 500

int  b[MAXN],array[ 4 ][MAXN], * sa, * nsa, * rank, * nrank,height[MAXN],len,n,m,mnlen[MAXN],mxlen[MAXN];
char  str[ 4001 ][ 205 ],ss[MAXN];


void  make_sa(){
    
int  i,k;

    sa
= array[ 0 ];
    nsa
= array[ 1 ];
    rank
= array[ 2 ];
    nrank
= array[ 3 ];

    memset(b,
0 , sizeof (b));
    
for (i = 0 ;i < n;i ++ )
        b[ss[i]]
++ ;
    
for (i = 1 ;i <= 256 ;i ++ )
        b[i]
+= b[i - 1 ];
    
for (i = n - 1 ;i >= 0 ;i -- )
        sa[
-- b[ss[i]]] = i;

    
for (rank[sa[ 0 ]] = 0 ,i = 1 ;i < n;i ++ ){
        rank[sa[i]]
= rank[sa[i - 1 ]];
        
if (ss[sa[i]] != ss[sa[i - 1 ]])
            rank[sa[i]]
++ ;
    }

    
for (k = 1 ;k < &&  rank[sa[n - 1 ]] < n - 1 ;k *= 2 ){
        
for (i = 0 ;i < n;i ++ )
            b[rank[sa[i]]]
= i;
        
for (i = n - 1 ;i >= 0 ;i -- )
            
if (sa[i] - k >= 0 )
                nsa[b[rank[sa[i]
- k]] -- ] = sa[i] - k;

        
for (i = n - k;i < n;i ++ )
            nsa[b[rank[i]]
-- ] = i;

        
for (nrank[nsa[ 0 ]] = 0 ,i = 1 ;i < n;i ++ ){
            nrank[nsa[i]]
= nrank[nsa[i - 1 ]];
            
if (rank[nsa[i]] != rank[nsa[i - 1 ]]  ||  rank[nsa[i] + k] != rank[nsa[i - 1 ] + k])
                nrank[nsa[i]]
++ ;
        }

        
int   * t = sa;sa = nsa;nsa = t;
        t
= rank;rank = nrank;nrank = t;
    }
}

void  cal_height(){
    
int  i,j,k;
    
for (i = 0 ,k = 0 ;i < n;i ++ ){
        
if (rank[i] == 0 )
            height[rank[i]]
= 0 ;
        
else {
            
for (j = sa[rank[i] - 1 ];ss[i + k] == ss[j + k];k ++ );
            height[rank[i]]
= k;
            
if (k > 0 )
                k
-- ;
        }
    }
}

void  make_mxlen(){
    memset(mxlen,
0 , sizeof (mxlen));
    
int  i,mn = INT_MAX;
    mxlen[
0 ] = 0 ;
    
for (i = 1 ;i < n;i ++ ){
        
if (height[i] < mn)
            mn
= height[i];
        
if (sa[i] < len){
            
if (mn == INT_MAX)
                mxlen[sa[i]]
= 0 ;
            
else
                mxlen[sa[i]]
= mn;
        }
        
else {
            mn
= INT_MAX;
        }
    }
    
bool  first = true ;
    mn
= INT_MAX;
    
for (i = n - 1 ;i >= 1 ;i -- ){
        
if (sa[i] < len){
            
if (mn != INT_MAX)
                
if (mn > mxlen[sa[i]])
                    mxlen[sa[i]]
= mn;
        }
        
else {
            mn
= height[i];
            first
= false ;
        }
        
if ( ! first  &&  height[i] < mn)
            mn
= height[i];
    }
}



int  main(){
    
int  i,j,t,mx,mxtag;
    
while (scanf( " %d " , & m)  &&  m){
        memset(mnlen,
0x7f , sizeof (mnlen));
        
for (i = 0 ;i < m;i ++ )
            scanf(
" %s " ,str[i]);
        len
= strlen(str[ 0 ]);
        str[
0 ][len ++ ] = ' # ' ;
        str[
0 ][len] = ' \0 ' ;
        
for (i = 1 ;i < m;i ++ ){
            strcpy(ss,str[
0 ]);
            strcat(ss,str[i]);
            n
= len + strlen(str[i]);
            ss[n
++ ] = ' $ ' ;
            ss[n]
= ' \0 ' ;
            make_sa();
            cal_height();

            
// 记录基串每一个位置与另外一个串的最长匹配长度
            make_mxlen();
            
            
// 求出每一个位置在和别的所有串跑后缀数组时所得的最长匹配中的最小值
             for (j = 0 ;j < len;j ++ )
                
if (mxlen[j] < mnlen[j])
                    mnlen[j]
= mxlen[j];
        }
        strcpy(ss,str[
0 ]);
        n
= len;

        
// 若有多个匹配符合答案则输出字典序最小的
        
// 估需要对基串重建后缀数组
        make_sa();
        mx
= 0 ;
        
for (i = 1 ;i < n;i ++ ){
            
if (mnlen[sa[i]] > mx){
                mx
= mnlen[sa[i]];
                mxtag
= sa[i];
            }
        }
        
if (mx){
            
for (i = 0 ;i < mx;i ++ )
                printf(
" %c " ,ss[mxtag + i]);
            printf(
" \n " );
        }
        
else
            printf(
" IDENTITY LOST\n " );
    }
    
return   0 ;
}

你可能感兴趣的:(entity)