leetcode第105场双周赛 3 - DP 4 - 并查集 + 思维 + 数学

比赛传送门

6394. 字符串中的额外字符

使用动态规划求解
详见代码:

class Solution {
	public:
	int minExtraChar(string s, vector<string>& ct) {
		int n=s.size();
		vector<int> dp(n+1,n);
		dp[0]=0;
		for(int i=0;i<n;++i){
			for(auto a:ct){
				if(s.substr(i,a.size())==a){
					dp[i+a.size()]=min(dp[i+a.size()],dp[i]);//以匹配上的字符串转移状态
				}
			}
			dp[i+1]=min(dp[i+1],dp[i]+1);//假设当前位置无法匹配字典中的字符串
		}
		return dp[n];
	}
};

2709. 最大公约数遍历

朴素的判断两两之间是否相连,TLE
我们可以首先预处理出所有数的质因数,之后将这些数与质因数构成并查集,最后判断是不是构成的完整的一个并查集即可

const int maxm=1e5+5;
vector<int> fac[maxm+5];
bool f=false;
int root[maxm<<1];
class Solution {
	public:
	void pre(){//预处理范围内的数,初步建立值与因子之间的关系
		if(!f)
			for(int i=2;i<=maxm;++i){
				if(fac[i].empty()){
					for(int j=i;j<=maxm;j+=i)
						fac[j].push_back(i);
				}
			}
		f=true;
		for(int i=0;i<maxm<<1;++i) root[i]=i;//并查集初始化
	}
	bool canTraverseAllPairs(vector<int>& nums) {
		pre();
		int n=nums.size();
		function<int(int)> findroot = [&](int x) {
			if (root[x] != x) root[x] = findroot(root[x]);
			return root[x];
		};
		for(int i=0;i<n;++i){//对每个数的因子进行连接
			for(int p:fac[nums[i]]){
				int x=findroot(i),y=findroot(n+p);
				if(x==y) continue;
				root[x]=y;
			}
		}
		unordered_set<int> st;
		for(int i=0;i<n;++i) st.insert(findroot(i));
		return st.size()==1;
	}
};
posted on 2023-05-28 00:20  Qiansui  阅读(5)  评论(0编辑  收藏  举报