LeetCode5803. 最长公共子路径(哈希+二分)
Posted live4m
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode5803. 最长公共子路径(哈希+二分)相关的知识,希望对你有一定的参考价值。
题意:
一个国家由 n 个编号为 0 到 n - 1 的城市组成。在这个国家里,每两个 城市之间都有一条道路连接。
总共有 m 个编号为 0 到 m - 1 的朋友想在这个国家旅游。他们每一个人的路径都会包含一些城市。
每条路径都由一个整数数组表示,每个整数数组表示一个朋友按顺序访问过的城市序列。
同一个城市在一条路径中可能 重复 出现,但同一个城市在一条路径中不会连续出现。
给你一个整数 n 和二维数组 paths ,
其中 paths[i] 是一个整数数组,表示第 i 个朋友走过的路径,
请你返回 每一个 朋友都走过的 最长公共子路径 的长度,如果不存在公共子路径,请你返回 0 。
一个 子路径 指的是一条路径中连续的城市序列。
数据范围:
1 <= n <= 1e5
m == paths.length
2 <= m <= 1e5
sum(paths[i].length) <= 1e5
0 <= paths[i][j] < n
paths[i] 中同一个城市不会连续重复出现。
解法:
二分答案mid,
哈希+map,对于路径[0,m-1],
对于path[i],枚举所有长度为mid的子路径,
如果map中该路径的哈希值已经被标记为i,那么更新为i+1.
只要某个哈希值被标记到m了,就说明存在长度为mid的子路径,在所有人的路径中都出现过.
二分复杂度O(log),check复杂度O(1e5*log).
总复杂度O(1e5*log*log).
code:
#define PI pair<int,int>
const int maxm=1e5+5;
const int mod1=1e9+7;
const int mod2=1e9+9;
const int p1=1331;
const int p2=131;
int base1[maxm];
int base2[maxm];
class Solution {
public:
vector<vector<int> >p;
vector<vector<int> >h1,h2;
int n,m;
bool check(int mid){
map<PI,int>mp;
for(int i=0;i<m;i++){
int len=p[i].size();
for(int j=mid-1;j<len;j++){
int l=j-mid+1,r=j;
int H1=((h1[i][r]-(l==0?0:1ll*base1[r-l+1]*h1[i][l-1]))%mod1+mod1)%mod1;
int H2=((h2[i][r]-(l==0?0:1ll*base2[r-l+1]*h2[i][l-1]))%mod2+mod2)%mod2;
if(i==0){
mp[{H1,H2}]=1;
}else if(mp.count({H1,H2})&&mp[{H1,H2}]==i){
if(i==m-1)return 1;
else mp[{H1,H2}]=i+1;
}
}
}
return 0;
}
int solve(){
//init
base1[0]=1;
for(int i=1;i<maxm;i++)base1[i]=1ll*base1[i-1]*p1%mod1;
base2[0]=1;
for(int i=1;i<maxm;i++)base2[i]=1ll*base2[i-1]*p2%mod2;
//
for(int i=0;i<m;i++){
int len=p[i].size();
h1[i].resize(len);
h2[i].resize(len);
for(int j=0;j<len;j++){
if(j==0){
h1[i][j]=p[i][j]+1;
h2[i][j]=p[i][j]+1;
}else{
h1[i][j]=(1ll*h1[i][j-1]*p1%mod1+(p[i][j]+1))%mod1;
h2[i][j]=(1ll*h2[i][j-1]*p2%mod2+(p[i][j]+1))%mod2;
}
}
}
//
int ans=0;
int l=1,r=p[0].size();
while(l<=r){
int mid=(l+r)/2;
if(check(mid))ans=mid,l=mid+1;
else r=mid-1;
}
return ans;
}
int longestCommonSubpath(int nn, vector<vector<int>>& pp) {
n=nn,p=pp,m=pp.size();
h1.resize(m);h2.resize(m);
int ans=solve();
return ans;
}
};
以上是关于LeetCode5803. 最长公共子路径(哈希+二分)的主要内容,如果未能解决你的问题,请参考以下文章