题解:字符串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;
}