题意:求最长公共子串
思路:把两个串Hash,然后我们把短的作为LCS的最大可能值,然后二分长度,每次判断这样二分可不可以。判断时,先拿出第一个母串所有len长的子串,排序,然后枚举第二个母串len长度字串,二分查找在第一个母串的子串中存不存在。
代码:
#include<cmath> #include<stack> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include <iostream> #include<algorithm> using namespace std; typedef long long ll; typedef unsigned long long ull; const int maxn = 100000 + 10; const ull seed = 131; const int INF = 0x3f3f3f3f; const int MOD = 1000000007; ull hs[maxn], hp[maxn], fac[maxn], q[maxn]; int len1, len2; char s[maxn], p[maxn]; ull get_hash(ull *h, int l, int r){ return h[r] - h[l - 1] * fac[r - l + 1]; } bool check(int len){ int cnt = 0; for(int i = 1; i + len - 1 <= len1; i++){ q[cnt++] = get_hash(hs, i, i + len - 1); } sort(q, q + cnt); for(int i = 1; i + len - 1 <= len2; i++){ ull aim = get_hash(hp, i, i + len - 1); if(binary_search(q, q + cnt, aim)) return true; } return false; } int main(){ fac[0] = 1; for(int i = 1; i < maxn; i++) fac[i] = fac[i - 1] * seed; while(~scanf("%s%s", s + 1, p + 1)){ len1 = strlen(s + 1); len2 = strlen(p + 1); hs[0] = hp[0] = 0; for(int i = 1; i <= len1; i++) hs[i] = hs[i - 1] * seed + (s[i] - 'a'); for(int i = 1; i <= len2; i++) hp[i] = hp[i - 1] * seed + (p[i] - 'a'); int l = 0, r = min(len1, len2); int ans = 0; while(l <= r){ int m = (l + r) >> 1; if(check(m)){ l = m + 1; ans = m; } else{ r = m - 1; } } printf("%d ", ans); } return 0; }