Longest Common Palindrome Substring

题解:字符串hash,实测rabinkarp 算法比直接求hash值要慢

1 直接求  (27ms)

#include 
using namespace std;
typedef long long LL;
typedef int lint;
const lint maxn = 100000 + 5;
char str1[maxn],str2[maxn],ss1[maxn],ss2[maxn];
unsigned long long sa1[maxn],sa2[maxn],sa11[maxn],sa22[maxn],mypow[maxn];
lint ans;
void init();
bool judge( lint len ){
    lint len1 = strlen( str1 );
    lint len2 = strlen( str2 );
    if( len > len1 || len > len2 ) return false;
    vector ve;
    for( lint i = 0;i + len <= len2;i++  ){
        unsigned long long t1 = sa2[i] - sa2[i+len]*mypow[len];
        unsigned long long t2 = sa22[len2-i-len] - sa22[len2-i]*mypow[len];
        if( t1 == t2 ) ve.push_back( t1 );
    }
    sort( ve.begin(),ve.end() );
    for( lint i = 0;i + len <= len1;i++ ){
        unsigned long long t1 = sa1[i] - sa1[i+len]*mypow[len];
        unsigned long long t2 = sa11[len1-i-len] - sa11[len1-i]*mypow[len];
        if( t1 == t2 ){
            lint p = lower_bound( ve.begin(),ve.end(),t1 ) - ve.begin() ;
            if( p != ve.size() && ve[p] == t1 ) return true;
        }
    }
    return false;
}
void solve0(){
    lint len1 = strlen( str1 );
    lint len2 = strlen( str2);
    lint l = 0,r = max( len1,len2 )+1;
    r += ( (r%2)?1:0 );
    while( l != r-2 ){
        lint mid = l + (r-l >> 1);
        if( mid%2 ) mid--;
        if( judge(mid) ){
            l = mid;
        }else{
            r = mid;
        }
    }
    ans = max( ans,l );
}
void solve1(){
    lint len1 = strlen(str1);
    lint len2 = strlen(str2);
    lint l = -1,r = max( len1,len2 )+1;
    r += ( (r%2)?0:1 );
    while( l != r-2 ){
        lint mid = l + (r-l >> 1);
        if( mid%2 == 0 )mid--;
        if( judge(mid) ){
            l = mid;
        }else{
            r = mid;
        }
    }
    ans = max( ans,l );
}
void getsa(){
    lint len1 = strlen( str1 );
    lint len2 = strlen( str2 );
    sa1[len1] = 0;
    for( lint i = len1-1;i >= 0;i-- ){
        sa1[i] = sa1[i+1]*26 + str1[i] - 'a';
    }
    sa11[len1] = 0;
    for( lint i = len1-1;i >= 0;i-- ){
        sa11[i] = sa11[i+1]*26 + ss1[i] - 'a';
    }
    sa2[len2] = 0;
    for( lint i = len2-1;i >= 0;i-- ){
        sa2[i] = sa2[i+1]*26+str2[i] - 'a';
    }
    sa22[len2] = 0;
    for( lint i = len2-1;i >= 0;i-- ){
        sa22[i] = sa22[i+1]*26 + ss2[i] - 'a';
    }
}
int main()
{
    //freopen("C:\\Users\\qqq\\Desktop\\654.txt","r",stdin);
    mypow[0] = 1;
    for( lint i = 1;i <= maxn;i++ ){
        mypow[i] = mypow[i-1]*26;
    }
    //cout << (unsigned long long )1520261030106 / 26 << endl;
    //cout << (unsigned long long )2637003226 / 26 << endl;
    while( ~scanf("%s%s",str1,str2)  ){ //58471578081
        ans = 0;
        strcpy( ss1,str1 );
        lint len = strlen( str1 );
        reverse( ss1,ss1+len );
        len = strlen( str2 );
        strcpy( ss2,str2 );
        reverse( ss2,ss2+len );
        //init();
        getsa();
        solve1();
        solve0();
        printf("%d\n",ans);
    }
 
    return 0;
}

2.rabinkarp(61ms)

#include 
using namespace std;
typedef long long LL;
typedef int lint;
const lint maxn = 100000 + 5;
char str1[maxn],str2[maxn],ss1[maxn],ss2[maxn];
unsigned long long sa1[maxn],sa2[maxn],sa11[maxn],sa22[maxn],mypow[maxn],hash1[maxn],rehash1[maxn],hash2[maxn],rehash2[maxn];
lint ans;
void init();
bool judge( lint len ){
    lint len1 = strlen( str1 );
    lint len2 = strlen( str2 );
    if( len > len1 || len > len2 ) return false;
    vector ve;
    hash1[len1-len] = sa1[len1-len];
    for( lint i = len1 - len-1;i >= 0;i-- ){
        hash1[i] = hash1[i+1]-mypow[len-1]*(str1[i+len]-'a');
        hash1[i] = hash1[i]*26 + str1[i]-'a';
    }
    rehash1[len1-len] = sa11[len1-len];
    for( lint i = len1-len-1;i >= 0;i-- ){
        rehash1[i] = rehash1[i+1] - mypow[len-1]*(ss1[i+len]-'a');
        rehash1[i] = rehash1[i]*26+ss1[i] - 'a';
    }
    for( lint i = 0;i <= len1-len;i++ ){
        if( hash1[i] == rehash1[len1-i-len] ) ve.push_back( hash1[i] );
    }
    sort( ve.begin(),ve.end() );
    hash2[len2-len] = sa2[len2-len];
    for( lint i = len2 - len-1;i >= 0;i-- ){
        hash2[i] = hash2[i+1]-mypow[len-1]*(str2[i+len]-'a');
        hash2[i] = hash2[i]*26 + str2[i]-'a';
    }
    rehash2[len2-len] = sa22[len2-len];
    for( lint i = len2-len-1;i >= 0;i-- ){
        rehash2[i] = rehash2[i+1] - mypow[len-1]*(ss2[i+len]-'a');
        rehash2[i] = rehash2[i]*26+ss2[i] - 'a';
    }
    for( lint i = 0;i <= len2-len;i++ ){
        if( hash2[i] == rehash2[len2-i-len] ){
            lint p = lower_bound(ve.begin(),ve.end(),hash2[i]) - ve.begin();
            if( p < ve.size() && ve[p] == hash2[i] ) return true;
        }
    }
    return false;
}
void solve0(){
    lint len1 = strlen( str1 );
    lint len2 = strlen( str2);
    lint l = 0,r = max( len1,len2 )+1;
    r += ( (r%2)?1:0 );
    while( l != r-2 ){
        lint mid = l + (r-l >> 1);
        if( mid%2 ) mid--;
        if( judge(mid) ){
            l = mid;
        }else{
            r = mid;
        }
    }
    ans = max( ans,l );
}
void solve1(){
    lint len1 = strlen(str1);
    lint len2 = strlen(str2);
    lint l = -1,r = max( len1,len2 )+1;
    r += ( (r%2)?0:1 );
    while( l != r-2 ){
        lint mid = l + (r-l >> 1);
        if( mid%2 == 0 )mid--;
        if( judge(mid) ){
            l = mid;
        }else{
            r = mid;
        }
    }
    ans = max( ans,l );
}
void getsa(){
    lint len1 = strlen( str1 );
    lint len2 = strlen( str2 );
    sa1[len1] = 0;
    for( lint i = len1-1;i >= 0;i-- ){
        sa1[i] = sa1[i+1]*26 + str1[i] - 'a';
    }
    sa11[len1] = 0;
    for( lint i = len1-1;i >= 0;i-- ){
        sa11[i] = sa11[i+1]*26 + ss1[i] - 'a';
    }
    sa2[len2] = 0;
    for( lint i = len2-1;i >= 0;i-- ){
        sa2[i] = sa2[i+1]*26+str2[i] - 'a';
    }
    sa22[len2] = 0;
    for( lint i = len2-1;i >= 0;i-- ){
        sa22[i] = sa22[i+1]*26 + ss2[i] - 'a';
    }
}
int main()
{
    //freopen("C:\\Users\\qqq\\Desktop\\654.txt","r",stdin);
    mypow[0] = 1;
    for( lint i = 1;i <= maxn;i++ ){
        mypow[i] = mypow[i-1]*26;
    }
    //cout << (unsigned long long )1520261030106 / 26 << endl;
    //cout << (unsigned long long )2637003226 / 26 << endl;
    while( ~scanf("%s%s",str1,str2)  ){ //58471578081
        ans = 0;
        strcpy( ss1,str1 );
        lint len = strlen( str1 );
        reverse( ss1,ss1+len );
        len = strlen( str2 );
        strcpy( ss2,str2 );
        reverse( ss2,ss2+len );
        //init();
        getsa();
        solve1();
        solve0();
        printf("%d\n",ans);
    }
 
    return 0;
}

 

你可能感兴趣的:(字符串,hash,字符串hash)