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 }