bzoj 4084 双旋转字符串
给两个集合A,B,找满足要求的(a,b)的对数,可以计算对于a,哪些b成立.
还有就是字符串hash的使用,感觉平时用字符串hash太少了.
1 /************************************************************** 2 Problem: 4084 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:6456 ms 7 Memory:290272 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <set> 12 #include <vector> 13 #include <algorithm> 14 #define N 8000010 15 #define Base 31 16 #define Mod 1000000007 17 using namespace std; 18 19 typedef long long dnt; 20 21 int n, m, ln, lm; 22 char *sa[N], *sb[N]; 23 char buf_arr[N], *buf=buf_arr; 24 dnt fx[N], sx[N], pow[N]; 25 int fail[N]; 26 multiset<int> stb; 27 28 int hash( char *s ) { 29 dnt rt = 0; 30 for( int i=0; s[i]; i++ ) 31 rt = (rt*Base + s[i]-'a') % Mod; 32 return rt; 33 } 34 void init_hash( int ln, char *s ) { // ln>=1 35 fx[0] = s[0]-'a'; 36 for( int j=1; j<ln; j++ ) 37 fx[j] = (fx[j-1]*Base + s[j]-'a') % Mod; 38 sx[ln-1] = s[ln-1]-'a'; 39 for( int j=ln-2; j>=0; j-- ) 40 sx[j] = ((s[j]-'a')*pow[ln-1-j] + sx[j+1]) % Mod; 41 } 42 void init_fail( char *s ) { 43 fail[0] = 0; 44 fail[1] = 0; 45 for( int i=1; s[i]; i++ ) { 46 int j=fail[i]; 47 while( j && s[j]!=s[i] ) j=fail[j]; 48 if( s[j]==s[i] ) 49 fail[i+1]=j+1; 50 else 51 fail[i+1]=0; 52 } 53 } 54 void work1() { // ln > lm 55 vector<int> vc; 56 int ll = (ln+lm)>>1; 57 dnt ans = 0; 58 for( int t=1; t<=n; t++ ) { 59 init_fail(sa[t]+ll); 60 for( int i=0; i<ll; i++ ) 61 buf[i] = sa[t][i]; 62 for( int i=0; i<ll; i++ ) 63 buf[ll+i] = sa[t][i]; 64 init_hash(ll+ll,buf); 65 vc.clear(); 66 int i=0, j=0; 67 while( i<ln-1 ) { 68 while( i<ln-1 && j<ln-ll && buf[i]==sa[t][ll+j] ) i++, j++; 69 if( j==ln-ll ) { 70 dnt v; 71 v = fx[i+(ll+ll-ln)-1]-fx[i-1]*pow[ll+ll-ln]; 72 v = (v%Mod+Mod) % Mod; 73 vc.push_back(v); 74 j = fail[ln-ll]; 75 } 76 if( i==ln-1 ) break; 77 while( j && sa[t][ll+j]!=buf[i] ) j=fail[j]; 78 if( sa[t][ll+j]!=buf[i] ) i++; 79 } 80 sort( vc.begin(), vc.end() ); 81 vc.erase( unique(vc.begin(),vc.end()), vc.end() ); 82 for( int t=0; t<vc.size(); t++ ) 83 ans += stb.count(vc[t]); 84 } 85 printf( "%lld\n", ans ); 86 } 87 void work3() { // ln = lm 88 vector<int> vc; 89 dnt ans = 0; 90 for( int i=1; i<=n; i++ ) { 91 init_hash(ln,sa[i]); 92 vc.clear(); 93 vc.push_back( sx[0] ); 94 for( int j=1; j<ln; j++ ) { 95 int v = ((dnt)sx[j]*pow[j]+fx[j-1]) % Mod; 96 vc.push_back(v); 97 } 98 sort( vc.begin(), vc.end() ); 99 vc.erase( unique(vc.begin(), vc.end()), vc.end() ); 100 for( int t=0; t<vc.size(); t++ ) 101 ans += stb.count(vc[t]); 102 } 103 printf( "%lld\n", ans ); 104 } 105 int main() { 106 scanf( "%d%d%d%d", &n, &m, &ln, &lm ); 107 if( ln>lm ) { 108 for( int i=1; i<=n; i++ ) { 109 scanf( "%s", buf ); 110 sa[i] = buf; 111 buf += ln+1; 112 } 113 for( int i=1; i<=m; i++ ) { 114 scanf( "%s", buf ); 115 sb[i] = buf; 116 buf += lm+1; 117 } 118 } else { 119 swap(n,m); 120 swap(ln,lm); 121 for( int i=1; i<=m; i++ ) { 122 scanf( "%s", buf ); 123 sb[i] = buf; 124 reverse( buf, buf+lm ); 125 buf += lm+1; 126 } 127 for( int i=1; i<=n; i++ ) { 128 scanf( "%s", buf ); 129 sa[i] = buf; 130 reverse( buf, buf+ln ); 131 buf += ln+1; 132 } 133 } 134 pow[0] = 1; 135 for( int i=1; i<=ln; i++ ) 136 pow[i] = pow[i-1]*Base % Mod; 137 for( int i=1; i<=m; i++ ) 138 stb.insert( hash(sb[i]) ); 139 if( ln!=lm ) 140 work1(); 141 else 142 work3(); 143 }