bzoj 4084 双旋转字符串

给两个集合A,B,找满足要求的(a,b)的对数,可以计算对于a,哪些b成立.

还有就是字符串hash的使用,感觉平时用字符串hash太少了.

 /**************************************************************
Problem: 4084
User: idy002
Language: C++
Result: Accepted
Time:6456 ms
Memory:290272 kb
****************************************************************/ #include <cstdio>
#include <set>
#include <vector>
#include <algorithm>
#define N 8000010
#define Base 31
#define Mod 1000000007
using namespace std; typedef long long dnt; int n, m, ln, lm;
char *sa[N], *sb[N];
char buf_arr[N], *buf=buf_arr;
dnt fx[N], sx[N], pow[N];
int fail[N];
multiset<int> stb; int hash( char *s ) {
dnt rt = ;
for( int i=; s[i]; i++ )
rt = (rt*Base + s[i]-'a') % Mod;
return rt;
}
void init_hash( int ln, char *s ) { // ln>=1
fx[] = s[]-'a';
for( int j=; j<ln; j++ )
fx[j] = (fx[j-]*Base + s[j]-'a') % Mod;
sx[ln-] = s[ln-]-'a';
for( int j=ln-; j>=; j-- )
sx[j] = ((s[j]-'a')*pow[ln--j] + sx[j+]) % Mod;
}
void init_fail( char *s ) {
fail[] = ;
fail[] = ;
for( int i=; s[i]; i++ ) {
int j=fail[i];
while( j && s[j]!=s[i] ) j=fail[j];
if( s[j]==s[i] )
fail[i+]=j+;
else
fail[i+]=;
}
}
void work1() { // ln > lm
vector<int> vc;
int ll = (ln+lm)>>;
dnt ans = ;
for( int t=; t<=n; t++ ) {
init_fail(sa[t]+ll);
for( int i=; i<ll; i++ )
buf[i] = sa[t][i];
for( int i=; i<ll; i++ )
buf[ll+i] = sa[t][i];
init_hash(ll+ll,buf);
vc.clear();
int i=, j=;
while( i<ln- ) {
while( i<ln- && j<ln-ll && buf[i]==sa[t][ll+j] ) i++, j++;
if( j==ln-ll ) {
dnt v;
v = fx[i+(ll+ll-ln)-]-fx[i-]*pow[ll+ll-ln];
v = (v%Mod+Mod) % Mod;
vc.push_back(v);
j = fail[ln-ll];
}
if( i==ln- ) break;
while( j && sa[t][ll+j]!=buf[i] ) j=fail[j];
if( sa[t][ll+j]!=buf[i] ) i++;
}
sort( vc.begin(), vc.end() );
vc.erase( unique(vc.begin(),vc.end()), vc.end() );
for( int t=; t<vc.size(); t++ )
ans += stb.count(vc[t]);
}
printf( "%lld\n", ans );
}
void work3() { // ln = lm
vector<int> vc;
dnt ans = ;
for( int i=; i<=n; i++ ) {
init_hash(ln,sa[i]);
vc.clear();
vc.push_back( sx[] );
for( int j=; j<ln; j++ ) {
int v = ((dnt)sx[j]*pow[j]+fx[j-]) % Mod;
vc.push_back(v);
}
sort( vc.begin(), vc.end() );
vc.erase( unique(vc.begin(), vc.end()), vc.end() );
for( int t=; t<vc.size(); t++ )
ans += stb.count(vc[t]);
}
printf( "%lld\n", ans );
}
int main() {
scanf( "%d%d%d%d", &n, &m, &ln, &lm );
if( ln>lm ) {
for( int i=; i<=n; i++ ) {
scanf( "%s", buf );
sa[i] = buf;
buf += ln+;
}
for( int i=; i<=m; i++ ) {
scanf( "%s", buf );
sb[i] = buf;
buf += lm+;
}
} else {
swap(n,m);
swap(ln,lm);
for( int i=; i<=m; i++ ) {
scanf( "%s", buf );
sb[i] = buf;
reverse( buf, buf+lm );
buf += lm+;
}
for( int i=; i<=n; i++ ) {
scanf( "%s", buf );
sa[i] = buf;
reverse( buf, buf+ln );
buf += ln+;
}
}
pow[] = ;
for( int i=; i<=ln; i++ )
pow[i] = pow[i-]*Base % Mod;
for( int i=; i<=m; i++ )
stb.insert( hash(sb[i]) );
if( ln!=lm )
work1();
else
work3();
}
上一篇:查看windows、linux的SN


下一篇:Ubuntu12.04 中文输入法设置