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
DebugLog
带取模的哈希值用 unsigned long long 存 ,溢出会错
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 存 ,溢出会错
相关文章推荐
- javascript中的函数Function
- javascript的作用域
- 2015第35周五JavaScript变量
- 【ExtJs】使用Cookie、切换主题和语言
- extjs实现多国语音切换
- JSON深入浅出
- JavaScript学习笔记之Array
- JavaScript基础2——变量、作用域和内存
- Js 事件大全
- JS 函数柯里化
- head first 一起实现js无缝上下滚动效果
- js跑马灯效果
- JavaScript内核笔记04-数组
- 【写一个自己的js库】 3.添加几个处理字符串的方法
- js mouseover/mouseout不停地循环
- JavaScript基础1——基本语法和数据类型
- JavaScript基础-arguments
- js的2种继承方式详解
- 利用fastjson反序列化json为对象和对象数组
- __proto__ 与prototype的区别,js函数声明与创建