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 }
View Code
转载于:https://www.cnblogs.com/idy002/p/4580844.html
bzoj 4084 双旋转字符串相关推荐
- 4084: [Sdoi2015]双旋转字符串
4084: [Sdoi2015]双旋转字符串 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 394 Solved: 161 [Submit][St ...
- [bzoj4084][Sdoi2015]双旋转字符串_hash
双旋转字符串 bzoj-4084 Sdoi-2015 题目大意:给定两个字符串集合 S 和 T .其中 S 中的所有字符串长度都恰好为 N ,而 T 中所有字符串长度都恰好为 M .且 N+M 恰好为 ...
- 【BZOJ】4084: [Sdoi2015]双旋转字符串 哈希
传送门:bzoj4084 题解 题面非常坑!!! 要求的是Si+TjSi+TjS_i+T_j,但实际上任意Tj+SiTj+SiT_j+S_i也可以算. AC的程序跑出的两组数据: input: 1 1 ...
- BZOJ 4084 [Sdoi2015]双旋转字符串
题解:hash 至今不会unsigned long long 的输出 把B扔进map 找A[mid+1][lenA]在A[1][mid]中的位置 把A[1][mid]贴两遍(套路) 枚举A[mid+1 ...
- 【bzoj4084】【sdoi2015】双旋转字符串
题解 首先题中说了$n>=m$; 分成的循环串左右两边为本质相同的单循环串循环串,分别长为$l = \frac{n + m}{2} $; 所以$S$串的前$l$位为双循环串的一半$S1$,后一半 ...
- 代码随想录算法训练营第八天|344.反转字符串 541. 反转字符串II 剑指Offer 05.替换空格 151.翻转字符串里的单词 剑指Offer58-II.左旋转字符串
一.344.反转字符串 题目:编写一个函数,其作用是将输入的字符串反转过来.输入字符串以字符数组 char[] 的形式给出. 不要给另外的数组分配额外的空间,你必须原地修改输入数组.使用 O(1) 的 ...
- 【编程题目】左旋转字符串 ☆
26.左旋转字符串(字符串) 题目: 定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部. 如把字符串 abcdef 左旋转 2 位得到字符串 cdefab.请实现字符串左旋转的函数. ...
- 经典算法面试题目-判断s2是否是s1的旋转字符串(1.8)
题目 Assume you have a method isSubstring which checks if one word is a substring of another. Given tw ...
- 【剑指offer-Java版】42翻转单词顺序VS左旋转字符串
反转单词顺序以及左旋转字符串:输入一个英文句子,翻转句子中的单词顺序,单词内部的字母顺序是不变的 – I am a student. -> student. am I 第一步,翻转句子中的所有字 ...
最新文章
- grep 正则表达式及选项以及注意
- Supervisor 守护你的进程
- python中list[1啥意思_详解Python中list[::-1]的几种用法
- 安装mysql5.7出现问题_本地安装Mysql5.7过程中出现的一系列问题
- 【转】Linux如何在系统启动时自动加载模块
- java用对话框输出计算结果_Java怎么实现输入一个string表达式然后输出计算的结果...
- bootstrap table 服务器端分页--ashx+ajax
- C语言编写程序11到20的和,C语言编程 菜鸟练习100题(11-20)
- 学计算机的学数学分析吗,学计算机专业是不是对数学的要求很高?
- Multistage GAN for Fabric Defect Detection 用于织物检测的多级GAN
- 自动弹琴助手使用及制谱教程
- Eclipse增加代码虚线对齐
- Google maps及51ditu的图片切割及存储方法2
- 转Genymetion
- YOLO-MASK对图像数据集进行清洗
- 知识点四 图论:dijkstra (HDU 2544 +HDU 1874)
- 2021高性价比蓝牙耳机榜单,学生党最爱五款平价蓝牙耳机分享
- html文本框自动下拉列表,HTML input输入框实现的动态下拉列表选择
- 计算机二级选择题记忆知识点
- 提高素质,讲文明树新风