您的位置:首页 > Web前端 > JavaScript

JSOI2013编程作业

2015-08-28 23:53 721 查看
大致问题是给你两个串,S与T,要求求S有多少子串与T匹配。匹配定义为两个串大写字母位置及内容一模一样,小写字母是可替换的。详见样例

Input

3 //数据组数

AiBjCiDECjDiFGC

AaBiCaDECiDaFGC

cDEcDEbDE

aDEbDE

ccddef

aab

Output

1

1

2

这题可以用Hash解决

对于小写字母,我们记录一个小写字母与上一个和它相同的小写字母的距离la[],和下一个与他相同的小写字母的距离nx[]。

先把T串的nx[]给hash起来。

再在S串线性扫一遍,维护长度为|T|的子串hash值。即加入一个新小写字母要将他上一个与他相同小写字母在hash值里的位置赋上值。

大写字母的hash值就是MAX_nx[]~MAX_nx[]+26

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std ;

typedef  long long ull ;

int Q , i , j , k , n , m , l[2] ;

ull  hs[2][3] , mo[3] = { 128760641,100000081 , 1196033  } ;

char s[2][1000010] ;

struct node {
int la , nx ;// all record posi of changing
}d[2][1000010] ;

int w[27] ;

void Preprocess( int p , int n ) {
int i , j , k ;
memset( w , 255 , sizeof w ) ;
memset( d[p] , 0 , sizeof d[p] ) ;
for( i=0 ; i<n ; i++ ) {
if( s[p][i] > 'Z' ) {
if(  w[ s[p][i] - 'a' ]!=-1 ) d[p][i].la = i - w[ s[p][i] - 'a' ] ,
d[p][  w[ s[p][i] - 'a' ] ].nx = i -  w[ s[p][i] - 'a' ] ;
w[ s[p][i] - 'a' ] = i ;
}
}
}

// We communi that 0 ~ l[1]-1 is lowercase letter posi changing , while l[1]+25  uppercase letter . And we should x( l[1]+26 )

ull Eraser[1000010] , X ;

void Hashize( int p , int n ) {
int i , j , k ;
ull ret[3]  ;
memset( ret , 0 , sizeof ret ) ;
for( i=0 ; i<n ; i++ ) {
for( k=0 ; k<3 ; k++ ) ret[k] = ret[k] * X  % mo[k] ;
if( s[p][i] > 'Z' ) {
if( i + d[p][i].nx < n ) {
for( k=0 ; k<3 ; k++ ) ret[k] = ( ret[k] + d[p][i].nx ) % mo[k] ;
Eraser[i] = d[p][i].nx  ;
}
} else {
for( k=0 ; k<3 ; k++ ) ret[k] = ( ret[k] + l[1] + s[p][i] - 'A' ) % mo[k] ;
Eraser[i] = l[1] + s[p][i] - 'A' ;
}
}
for( k=0 ; k<3 ; k++ ) hs[p][k] = ret[k] ;
}

ull inx[1000010][3] ;

int main() {
scanf("%d" , &Q ) ;
while( Q-- ) {
scanf("%s%s",s[0] , s[1] ) ;
l[0] = strlen( s[0] ) , l[1] = strlen( s[1] ) ;
Preprocess( 0 , l[0] ) ;
Preprocess( 1 , l[1] ) ;
X = ( l[1] + 26 ) ;
Hashize( 1 , l[1] ) ;
memset( Eraser , 0 , sizeof Eraser ) ;
Hashize( 0 , l[1] ) ;
for( inx[0][0] = inx[0][1] = inx[0][2]  = 1 , i = 1 ; i<=l[0] ; i++ )
for( k=0 ; k<3 ; k++ ) inx[i][k] = inx[i-1][k] * X % mo[k];
int ans = 0 ;
if( hs[0][0]==hs[1][0] && hs[0][1]==hs[1][1] && hs[0][2]==hs[1][2] ) ans ++ ;
for( i=l[1] ; i<l[0] ; i++ ) {
for( k=0 ; k<3 ; k++ ) hs[0][k] = ( ( hs[0][k] - inx[ l[1]-1 ][k] * Eraser[ i-l[1] ] ) % mo[k] + mo[k] ) % mo[k];
for( k=0 ; k<3 ; k++ ) hs[0][k] = hs[0][k] * X % mo[k];
if( s[0][i]  >'Z' ) {
if( d[0][i].la<l[1] ) {
for( k=0 ; k<3 ; k++ ) hs[0][k] = ( hs[0][k] + ( Eraser[ i-d[0][i].la ] = d[0][i].la ) * inx[ d[0][i].la ][k] ) % mo[k] ;
}
} else {
for( k=0 ; k<3 ; k++ ) hs[0][k] = ( hs[0][k] + ( Eraser[i] = ( s[0][i] - 'A' + l[1] ) ) ) % mo[k] ;
}
if( hs[0][0]==hs[1][0] && hs[0][1]==hs[1][1] && hs[0][2]==hs[1][2] ) ans ++ ;
}
printf("%d\n",ans ) ;
}
}


DebugLog

带取模的哈希值用 unsigned long long 存 ,溢出会错
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: