标签:子串 paths cnt int mid 数组 字符串 长度
给定n个数组,求这n个数组的最长公共子串的长度,例如:
paths = [[0,1,2,3,4], [2,3,4], [4,0,1,2,3]]
的最长公共子串为[2,3]
,长度为2。
这类问题可以使用字符串hash来解决,首先是二分最长公共子串的长度。对于每个二分的长度,都去check
是否存在该长度下的解。hash的主要目的是在O(1)时间得到每个数组的每个子串的hash值,这样就可以判断在相同长度下是否存在某个hash值在每个数组中都存在,即包含相同长度的子串。
typedef unsigned long long ULL;
const int N = 100010, P = 13771;
ULL h[N], p[N];
ULL get(int l, int r){
return h[r] - h[l - 1] * p[r - l + 1];
}
class Solution {
public:
vector<vector<int>> paths;
unordered_map<ULL, int> mp, vis;
bool check(int mid){
mp.clear();
for(int k = 0; k < paths.size(); k ++ ){
auto &a = paths[k];
p[0] = 1;
for(int i = 1; i <= a.size(); i ++ ){
h[i] = h[i - 1] * P + a[i - 1];
p[i] = p[i - 1] * P;
}
vis.clear();
for(int i = mid; i <= a.size(); i ++ ){
ULL t = get(i - mid + 1, i);
if(vis.count(t) == 0) {
mp[t] ++ ;
vis[t] = 1;
}
}
}
int cnt = 0;
for(auto &[u, v]: mp) cnt = max(cnt, v);
return cnt == paths.size();
}
int longestCommonSubpath(vector<vector<int>>& _paths) {
paths = _paths;
int l = 0, r = N;
for(auto &path: paths) r = min(r, (int)path.size());
while(l < r){
int mid = l + r + 1 >> 1;
if(check(mid)) l = mid;
else r = mid - 1;
}
return l;
}
};
Note:哈希函数的P可以调节以避免哈希冲突,一般调节顺序为131->1331->13331->133331
。
标签:子串,paths,cnt,int,mid,数组,字符串,长度 来源: https://blog.csdn.net/qq_40438165/article/details/118468092
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。