BNUOJ34990--Justice String (exkmp求最长公共前缀)
2015-05-19 13:07
309 查看
Justice String
Given two strings A and B, your task is to find a substring of A called justice string, which has the same length as B, and only has at most two characters different from B.Input
The first line of the input contains a single integer T, which is the number of test cases.For each test case, the first line is string A, and the second is string B.
Both string A and B contain lowercase English letters from a to z only. And the length of these two strings is between 1 and 100000, inclusive.
Output
For each case, first output the case number as "Case #x: ", and x is the case number. Then output a number indicating the start position of substring C in A, position is counted from 0. If there is no such substring C, output -1.And if there are multiple solutions, output the smallest one.
Sample Input
3 aaabcd abee aaaaaa aaaaa aaaaaa aabbb
Sample Output
Case #1: 2 Case #2: 0 Case #3: -1 题意:两个字符串, 求B在在A串出现的第一个位置, 可以允许最多两个字符不同。 做法: 依次枚举位置i, 然后求A[i, ...lena - 1]与B的最长公共前缀, 再求 A[i, i+lenb-1]的B的最长公共后缀。。 然后对于中间那一部分, 用多项式hash直接判断是否相等。
#include <bits/stdc++.h> using namespace std; const int seed = 1e9+7; const int MAXN = 1e5+10; typedef unsigned long long uLL; uLL _hash[2][MAXN]; string s1, s2; void Hash(string s, int d){ int len = s.size(); memset(_hash[d], 0, sizeof (_hash[d])); for (int i = 0; i < len; i++){ _hash[d][i] = (i ? _hash[d][i-1] : 0) * seed + s[i] - '0'; } } void pre_kmp(string &s, int m, int next[]){ next[0] = m; int j = 0; while (j + 1 < m && s[j] == s[j+1]){ j++; } next[1] = j; int k = 1; for (int i = 2; i < m; i++){ int p = next[k] + k - 1; int L = next[i-k]; if (i + L < p + 1){ next[i] = L; }else{ j = max(0, p-i+1); while (i+j < m && s[i+j] == s[j]){ j++; } next[i] = j; k = i; } } } void exkmp(string &str1, int len1, string &str2, int len2, int next[], int extend[]){ pre_kmp(str1, len1, next); int j = 0; while (j < len2 && j < len1 && str1[j] == str2[j]){ j++; } extend[0] = j; int k = 0; for (int i = 1; i < len2; i++){ int p = extend[k] + k - 1; int L = next[i-k]; if (i + L < p + 1){ extend[i] = L; }else{ j = max(0, p-i+1); while (i+j < len2 && j < len1 && str2[i+j] == str1[j]){ j++; } extend[i] = j; k = i; } } } int ex1[MAXN], ex2[MAXN], next[MAXN]; uLL bas[MAXN]; void pre_solve(){ bas[0] = 1; for (int i = 1; i < MAXN; i++){ bas[i] = bas[i-1] * seed; } } int main(){ //freopen("in.txt", "r", stdin); pre_solve(); int T, cas = 1; scanf ("%d", &T); while (T--){ cin >> s1 >> s2; int len1 = s1.size(); int len2 = s2.size(); Hash(s1, 0); Hash(s2, 1); string tmp1 = s1; string tmp2 = s2; reverse(tmp1.begin(), tmp1.end()); reverse(tmp2.begin(), tmp2.end()); exkmp(s2, len2, s1, len1, next, ex1); exkmp(tmp2, len2, tmp1, len1, next, ex2); int ans = -1; for (int i = 0; i < len1; i++){ int t1 = ex1[i]; int t2 = ex2[len1 - i - len2]; int L1 = i+t1, R1 = i+len2-t2-1; int L2 = t1, R2 = len2-t2-1; bool ok1 = ((t1 == len2) || (R1 <= L1+1)); uLL p1 = (_hash[0][R1-1] - _hash[0][L1] * bas[R1-1-L1]); uLL p2 = (_hash[1][R2-1] - _hash[1][L2] * bas[R2-1-L2]); bool ok2 = (p1 == p2); if (ok1 || ok2){ ans = i; break; } } printf("Case #%d: %d\n", cas++, ans); } return 0; }
相关文章推荐
- CSU 1598 最长公共前缀 KMP连续匹配
- hdoj 2594 Simpsons’ Hidden Talents 【KMP】【求串的最长公共前缀后缀】
- 求最长公共前缀和后缀—基于KMP的next数组
- 扩展KMP--求母串各后缀和模串的最长公共前缀
- CSU 1598 最长公共前缀 【KMP】
- 扩展KMP--求字符串S的所有后缀和字符串T的最长公共前缀
- HDU 2594 Simpsons’ Hidden Talents (KMP——前缀后缀最长公共串)
- EXKMP模版:最长共同前缀长度
- 扩展KMP(模式串与文本串的最长公共前缀)
- hdoj 2594 Simpsons’ Hidden Talents 【KMP】【求串的最长公共前缀后缀】
- LintCode 最长公共前缀
- 动态建树之——寻找最长公共前缀
- 查找字符串数组中最长的公共前缀字符串。
- leetcode-14-最长公共前缀
- leetcode-14. Longest Common Prefix(寻找字符串数组最长公共前缀)
- 寻找若干个字符串的最长公共前缀
- POJ 3080 Blue Jeans(KMP:最长连续公共子序列)
- poj 3080(3450) KMP(暴力也能过) 多个串的最长公共子串
- Longest Common Prefix字符串最长公共前缀问题
- LeetCode14最长公共前缀