给两个集合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();
}

bzoj 4084 双旋转字符串的更多相关文章

  1. [bzoj4084][Sdoi2015]双旋转字符串_hash

    双旋转字符串 bzoj-4084 Sdoi-2015 题目大意:给定两个字符串集合 S 和 T .其中 S 中的所有字符串长度都恰好为 N ,而 T 中所有字符串长度都恰好为 M .且 N+M 恰好为 ...

  2. BZOJ 4084 [Sdoi2015]双旋转字符串

    题解:hash 至今不会unsigned long long 的输出 把B扔进map 找A[mid+1][lenA]在A[1][mid]中的位置 把A[1][mid]贴两遍(套路) 枚举A[mid+1 ...

  3. 【bzoj4084】【sdoi2015】双旋转字符串

    题解 首先题中说了$n>=m$; 分成的循环串左右两边为本质相同的单循环串循环串,分别长为$l = \frac{n + m}{2} $; 所以$S$串的前$l$位为双循环串的一半$S1$,后一半 ...

  4. 剑指Offer面试题:34.翻转单词顺序VS左旋转字符串

    一.题目一:翻转单词顺序 1.1 题目说明 题目一:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变.为简单起见,标点符号和普通字母一样处理.例如输入字符串"I am a st ...

  5. 【面试题042】翻转单词顺序VS左旋转字符串

    [面试题042]翻转单词顺序VS左旋转字符串 题目一:     输入一个英文句子,反转句子中单词的顺序,但单词内字符的顺序不变.为简单起见,标点符号和普通字母一样处理.     例如输入字符串“I a ...

  6. lintcode :旋转字符串

    题目: 旋转字符串 给定一个字符串和一个偏移量,根据偏移量旋转字符串(从左向右旋转) 样例 对于字符串 "abcdefg". offset=0 => "abcdef ...

  7. 九度OJ 1362 左旋转字符串(Move!Move!!Move!!!)【算法】

    题目地址:http://ac.jobdu.com/problem.php?pid=1362 题目描述: 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运 ...

  8. LintCode 面试题 旋转字符串

    1.题目描述 题目链接:http://www.lintcode.com/zh-cn/problem/rotate-string/ 给定一个字符串和一个偏移量,根据偏移量旋转字符串(从左向右旋转) 2. ...

  9. 1289 大鱼吃小鱼 1305 Pairwise Sum and Divide 1344 走格子 1347 旋转字符串 1381 硬币游戏

    1289 大鱼吃小鱼 有N条鱼每条鱼的位置及大小均不同,他们沿着X轴游动,有的向左,有的向右.游动的速度是一样的,两条鱼相遇大鱼会吃掉小鱼.从左到右给出每条鱼的大小和游动的方向(0表示向左,1表示向右 ...

随机推荐

  1. Unity 发送游戏画面到 Winform

    一.首先看一下Unity界面: 设了2个摄像机,位置重叠,旋转相同,父子关系,在父摄像机上加上脚本A.cs,并将子摄像机复制给A脚本中的变量Cam: Cam用于为RenderTexture提供画面,P ...

  2. 一步步实现windows版ijkplayer系列文章之六——SDL2源码分析之OpenGL ES在windows上的渲染过程

    一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...

  3. node 相关网站

    包管理网站:https://www.npmjs.com/

  4. Mac配置Java开发环境

    笔者从Window上转到Mac上做开发,一切配置都要重新开始,开发环境配置介绍如下: 1. 下载JDK 从下面链接选择合适版本的安装包进行下载...笔者下载的是jdk-9.0.1 链接:http:// ...

  5. Oracle系统表外键的更名

    正在看的ORACLE教程是:Oracle系统表外键的更名. Oracle中表的外键是保证系统参照完整性的手段,而参照完整性是指分布在两个表中的列所满足的具有主从性质的约束关系.外键涉及到两个表,其中一 ...

  6. linux 安装软件

    apt-get install softname /安装软件apt-get update 是更新 /etc/apt/sources.list 和 /etc/apt/sources.list.d 中列出 ...

  7. php三种常用的加密解密算法

    方法一: /** * @param $string 要加密/解密的字符串 * @param string $operation 类型,ENCODE 加密:DECODE 解密 * @param stri ...

  8. hdu2642二维树状数组单点更新

    碰到这种题一定要注意坐标是不是有序的,也要注意坐标是不是有0的,有的话需要+1处理 #include<bits/stdc++.h> using namespace std; #define ...

  9. kafka删除topic数据

    一.概述 生产环境中,有一个topic的数据量非常大.这些数据不是非常重要,需要定期清理. 要求:默认保持24小时,某些topic 需要保留2小时或者6小时 二.清除方式 主要有3个: 1. 基于时间 ...

  10. 使用Ztree新增角色和编辑角色回显

    最近在项目中使用到了ztree,在回显时候费了点时间,特记录下来供下次参考. 1.新增角色使用ztree加载权限,由于权限不多,所以使用直接全部加载. 效果图: 具体涉及ztree代码: jsp中导入 ...