数据结构复习:最小生成树与KMP

最小生成树

生成树:一个连通无向图的生成子树,同时要求是树。也即在图的边集中选择n - 1条,将所有顶点连通

我们定义无向连通图的最小生成树为边权和最小的生成树

注意:只有连通图才有生成树,而对于非连通图,只存在生成森林

Kruskal算法

#include<bits/stdc++.h>
using namespace std;
const int MAX = 1e6+1;
struct NODE{//存放边 
	int u;
	int v;
	int w;
}e[MAX];
int cnt;//记录边的数量 
int fa[MAX];//并查集 记录祖先 
int flag;//标志 
int sum;//记录边权和 
int n,m;//点,边
int num;//记录加入边的数量
void add(int x,int y,int w){//加边 
	e[++cnt].u = x;
	e[cnt].v = y;
	e[cnt].w = w;
}
void ini(){//初始化 
	flag = 0;
	sum = 0;
	cnt = 0;
	num = 0; 
	for(int i = 1;i <= n;i++)
		fa[i] = i;
} 
int find(int x){
	if(fa[x] != x)//说明该结点还能向上溯源 
		fa[x] = find(fa[x]);//路径压缩,把该结点的父节点更新为根节点(祖先) 
	return fa[x];//返回祖先 
}
void kruskal(){
	for(int i = 1;i <= cnt;i++){
		int x = find(e[i].u);
		int y = find(e[i].v);
		if(x == y)//如果两个结点祖先相同,说明两点已经连通 
			continue;
		fa[x] = y;//否则赋值使其连通
		sum += e[i].w;//计算权值和 
		if(++num == n - 1){//加边条数等于n-1条时说明已经连通 
			flag = 1;
			break;
		}
	} 
} 
bool cmp(struct NODE a,struct NODE b){//重载sort函数 
	return a.w < b.w;
}
int main(){
	while(cin>>n>>m){//顶点数 边数 
		ini();
		while(m--) {
			int x, y, w;
			cin>>x>>y>>w;
			add(x, y, w);
		}
		sort(e,e+cnt,cmp);//按照边权排序
		kruskal();
		if(flag)
			printf("%d\n",sum);
		else{
			cout<<"无法生成最小生成树"<<endl;
		} 
	}
	return 0;
}

KMP

#include<bits/stdc++.h>
using namespace std;
char str[100010];//测试串(模式串)
char s[100010];//主串(被测串) 
int n[100010]={0};//next数组
void calnext(){
	int len = strlen(str);
	for(int j = 1,p = 0;j < len;j++){
		while(p > 0 && str[p] != str[j])//长度为1或者目前字符不匹配时利用失败函数提前跳转 
			p = n[p-1];//从上个字符匹配完位置开始匹配 
		if(str[p] == str[j])
			p++;
		n[j] = p;
		//cout<<j<<" "<<p<<endl;  
	}
	for(int i = 0;str[i] != '\0';i++)
			cout<<n[i]<<' ';
		cout<<endl;
} 
int kmp(){
	calnext();
	int len = strlen(str);//模式串的长度 
	for(int i = 0,j = 0;s[i] != '\0';i++){
		while(j > 0 && s[i] != str[j])
			j = n[j-1];
		if(s[i] == str[j])
			j++;
		if(j == len)//匹配完成
			return i - len + 1;
	}
	return -1;
}
int main(){
	cin>>s;
	cin>>str; 
	int flag = kmp();
	if(flag != -1){
		cout<<"匹配位置在:"<<flag; 
	}
	else
		cout<<"无法匹配"; 
	return 0; 
}
/*
	abbbbabab
	bbbba

*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值