hihocoder 1084 扩展KMP && 2014 北京邀请赛 Justice String

hihocoder 1084 : http://hihocoder.com/problemset/problem/1084

北京邀请赛 Just  String http://www.bnuoj.com/v3/problem_show.php?pid=34990

两道题同样的做法,题目基本内容是找到A的字串中和B串长度一样,且不同的字符个数不超过k个的置。

以hihocoder 1084为例, 是求有多少个A的字串的,与B串长度一样,且不同的字符个数不超过k。

分析:预处理hash,然后对每个字串进行判断,例如A[i~i+len-1] 和B[0~len-1], 首先找到一个A,B都相同的字符,然后从此出发找到长度尽可能大的完全相同的一截,这里可以用二分完成,然后再次找到一个对应位置A,B相同的字符,一旦不相同的字符个数超过k则立马终止,这样复杂度接近O(N*logN*k)。

代码:

 1 #include <bits/stdc++.h>
 2 #define pb push_back
 3 #define mp make_pair
 4 #define esp 1e-14
 5 #define lson   l, m, rt<<1
 6 #define rson   m+1, r, rt<<1|1
 7 #define sz(x) ((int)((x).size()))
 8 #define pf(x) ((x)*(x))
 9 #define pb push_back
10 #define pi acos(-1.0)
11 #define in freopen("solve_in.txt", "r", stdin);
12 #define bug(x) cerr << "Line : " << (x) <<  " >>>>>>\n";
13 #define TL cerr << "Time elapsed: " << (double)clock() / CLOCKS_PER_SEC * 1000 << " ms" << endl;
14 #define inf 0x0f0f0f0f
15
16 using namespace std;
17 typedef long long LL;
18 typedef unsigned long long ULL;
19 typedef map<LL, int> MPS;
20 typedef pair<int, int> PII;
21 typedef MPS::iterator IT;
22
23 const int maxn = 100000 + 100;
24 const int B = (int)1e6 + 9;
25
26 char sa[maxn], sb[maxn];
27 ULL pw[maxn], ha[maxn], hb[maxn];
28 int n, m, k;
29 void pre(){
30     pw[0] = 1;
31     for(int i = 1; i < maxn; i++)
32         pw[i] = pw[i-1]*B;
33 }
34 inline ULL cal(ULL h[], int l, int r, int len){
35     return h[l]-h[r+1]*pw[len];
36 }
37 inline int idx(char ch){
38     return ch - ‘a‘;
39 }
40 int main() {
41
42     pre();
43     while(scanf("%s%s%d", sa, sb, &k) == 3){
44         n = strlen(sa);
45         m = strlen(sb);
46         ha[n] = hb[m] = 0;
47         for(int i = n-1; i >= 0; i--)
48             ha[i] = ha[i+1]*B+idx(sa[i]);
49         for(int i = m-1; i >= 0; i--)
50             hb[i] = hb[i+1]*B+idx(sb[i]);
51         int ans = 0;
52         for(int i = 0; i <= n-m; i++){
53             int j = 0, x = 0;
54 //            bug(i)
55             while(x <= k && j < m){
56                 while(j < m && sa[i+j] != sb[j] && x <= k)
57                     j++, x++;
58 //                bug(j)
59                 if(j >= m || x > k) break;
60                 int l = j, r = m;
61                 while(l+1 < r){
62                     int mid = (l+r)>>1;
63 //                    bug(mid)
64                     ULL h1 = cal(ha, i+l, i+mid, mid-l+1);
65                     ULL h2 = cal(hb, l, mid, mid-l+1);
66                     if(h1 == h2)
67                         l = mid;
68                     else r = mid;
69                 }
70                 if(l != m-1)
71                 x++;
72                 j = l+2;
73             }
74             ans += x <= k;
75         }
76         printf("%d\n", ans);
77     }
78     return 0;
79 }

北京邀请赛同样的分析方法。

代码:

 1 #include <bits/stdc++.h>
 2 #define pb push_back
 3 #define mp make_pair
 4 #define esp 1e-14
 5 #define lson   l, m, rt<<1
 6 #define rson   m+1, r, rt<<1|1
 7 #define sz(x) ((int)((x).size()))
 8 #define pf(x) ((x)*(x))
 9 #define pb push_back
10 #define pi acos(-1.0)
11 #define in freopen("solve_in.txt", "r", stdin);
12 #define bug(x) cerr << "Line : " << (x) <<  " >>>>>>\n";
13 #define TL cerr << "Time elapsed: " << (double)clock() / CLOCKS_PER_SEC * 1000 << " ms" << endl;
14 #define inf 0x0f0f0f0f
15
16 using namespace std;
17 typedef long long LL;
18 typedef unsigned long long ULL;
19 typedef map<LL, int> MPS;
20 typedef pair<int, int> PII;
21 typedef MPS::iterator IT;
22
23 const int maxn = 100000 + 100;
24 const int B = (int)1e6 + 9;
25
26 char sa[maxn], sb[maxn];
27 ULL pw[maxn], ha[maxn], hb[maxn];
28 int n, m, k;
29 void pre() {
30     pw[0] = 1;
31     for(int i = 1; i < maxn; i++)
32         pw[i] = pw[i-1]*B;
33 }
34 inline ULL cal(ULL h[], int l, int r, int len) {
35     return h[l]-h[r+1]*pw[len];
36 }
37 inline int idx(char ch) {
38     return ch - ‘a‘;
39 }
40 int main() {
41
42     pre();
43     int T;
44     for(int t = scanf("%d", &T); t <= T; t++) {
45         k = 2;
46         scanf("%s%s", sa, sb);
47         n = strlen(sa);
48         m = strlen(sb);
49         ha[n] = hb[m] = 0;
50         for(int i = n-1; i >= 0; i--)
51             ha[i] = ha[i+1]*B+idx(sa[i]);
52         for(int i = m-1; i >= 0; i--)
53             hb[i] = hb[i+1]*B+idx(sb[i]);
54         int ans = -1;
55         for(int i = 0; i <= n-m; i++) {
56             int j = 0, x = 0;
57 //            bug(i)
58             while(x <= k && j < m) {
59                 while(j < m && sa[i+j] != sb[j] && x <= k)
60                     j++, x++;
61 //                bug(j)
62                 if(j >= m || x > k) break;
63                 int l = j, r = m;
64                 while(l+1 < r) {
65                     int mid = (l+r)>>1;
66 //                    bug(mid)
67                     ULL h1 = cal(ha, i+l, i+mid, mid-l+1);
68                     ULL h2 = cal(hb, l, mid, mid-l+1);
69                     if(h1 == h2)
70                         l = mid;
71                     else r = mid;
72                 }
73                 if(l != m-1)
74                     x++;
75                 j = l+2;
76             }
77             if(x <= k) {
78                 ans = i;
79                 break;
80             }
81         }
82         printf("Case #%d: %d\n", t, ans);
83     }
84     return 0;
85 }

时间: 2024-08-29 02:13:48

hihocoder 1084 扩展KMP && 2014 北京邀请赛 Justice String的相关文章

2014 北京邀请赛ABDHJ题解

A. A Matrix 点击打开链接 构造,结论是从第一行开始往下产生一条曲线,使得这条区间最长且从上到下递减, #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <stdio.h> #include <vector> #include <set> using namespace std; #defi

ACM-ICPC 2014北京邀请赛 H Happy Reverse [模拟]

题意:给出n个二进制串,可以把其中的一些0和1反转(即0变1,1变0),找出转化后n个串中的最大值和最小值的差值. 分析:思路就是把所有的串和反转的存在一个数组中,然后排序,找最大值和最小值的差,(如果是同一个串反转的就找第二大的和最小的或第二小和最大的中的最大值).注意假如只有一个串的话结果为0 DEBUG: 这题写了好久 1.第一次用vim,很爽,但是还没熟练 2.忽视了这题的范围,显然要用longlong 3.用了longlong后还WA,用脚本跑出来数据发现在longlong下,min的

2014北京邀请赛 Happy Reversal

H. Happy Reversal 64-bit integer IO format: %lld      Java class name: Main Elfness is studying in an operation "NOT". For a binary number A, if we do operation "NOT A", after that, all digits of A will be reversed. (e.g. A=1001101, af

BNUOJ 34985 Elegant String 2014北京邀请赛E题 动态规划 矩阵快速幂

Elegant String Time Limit: 1000msMemory Limit: 65536KB 64-bit integer IO format: %lld      Java class name: Main We define a kind of strings as elegant string: among all the substrings of an elegant string, none of them is a permutation of "0, 1,-, k

2014北京邀请赛(部分题解)

马上要去比赛了. 今天做了一下2014北京邀请赛,出了两道题目,感觉很水啊... 首先H题: H. Happy Reversal Time Limit: 1000ms Case Time Limit: 1000ms Memory Limit: 65536KB 64-bit integer IO format: %lld      Java class name: Main Submit Status PID: 34988 Font Size:  +   - Elfness is studying

BNUOJ 34985 Elegant String 2014北京邀请赛E题 矩阵快速幂

题目链接:http://acm.bnu.edu.cn/bnuoj/problem_show.php?pid=34985 题目大意:问n长度的串用0~k的数字去填,有多少个串保证任意子串中不包含0~k的某一个全排列 邀请赛上A的较多的一道题,比赛的时候死活想不出,回来之后突然就想通了,简直..... = =! 解题思路: 对于所有串我们都只考虑末尾最多有多少位能构成全排列的一部分(用l来表示),即最多有多少位不重复的数字出现,将问题转化为求末尾最多有k位能构成全排列的串的总数量 假设k为5,有一个

2014北京邀请赛E题-矩阵快速幂

题意:长度为n(1<=n<=10^18)的并且任意连续子串都不是0-k(1<=k<=9)的一个排列的字符串有多少种. 解法:矩阵快速幂.dp[i][j]表示i长度最后连续j个不同(即最后j个无重复,最后j+1个有重复)的字符串的个数.状态选好很重要.设计状态时最重要考虑是唯一性和可传递性,比赛时明明知道肯定是矩阵快速幂,但是一直没想到这个状态表示,自己设计的自己都不会转移. dp[i][j]有了后,后边加一个字符,这个字符可以是j之内的任意一个,也可以是j以外的,这样枚举每种情况,

2014北京邀请赛反思

北京嘛,我大天朝之帝都,当然是高手云集撒. 躺了21个小时的火车,历史以来最久了.旅社住"7天",一直以为"7天"是为情侣们准备的,事实估摸着也是这样.我哩个擦,厕所门不能锁,小小脑补了一下,顿时邪恶万分... 张逗彪找gf去了,被梁平君吼了,搞得我拒绝了同学周六早上带我逛北京的邀请.算了躺床睡觉. 开幕式,看到了会讲笑话的董适,果然是会讲段子!知道了他们信科院就有3个院士,呵呵,湖大总共几个院士? 热身赛,真忧伤!题目改了,没看到,一直在想tm别人能在1-50(实

2014北京邀请赛 F Football on Table

题目来源: http://acm.bnu.edu.cn/bnuoj/problem_show.php?pid=34986 题意: 一个人在玩桌面足球,有m行球员,每行球员有ai个,给出每个球员的宽度和相邻球员之间的距离,球从最左边射出,给出球的起点坐标跟方向向量,问能够到达最右边的概率. 思路:球员的相对位置固定,球员可以移动一定的距离.计算球经过球员的概率, 用1 - 球经过球员的概率 即为 可以穿过的概率. 枚举一遍所有行. 代码如下: const int Max_N = 105 ; dou