2021寒假训练9

2021-03-02个人赛9记录


前言

一、题目分析

A 关押罪犯 并查集

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
int dad[100010];
struct yyqxwyb
{
	int u;
	int v;
	int sum;
}zz[100010];
int find(int x)
{
	while (x != dad[x])x = dad[x];
	return x;
}
bool cmp(yyqxwyb y1, yyqxwyb y2)
{
	return y1.sum > y2.sum;
}
void unionn(int a, int b)
{
	int x1 = find(a);
	int x2 = find(b);
	if (x1 != x2)dad[x1] = x2;
}
int main()
{
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < 2 * n; i++)dad[i] = i;
	for (int i = 0; i < m; i++)cin >> zz[i].u >> zz[i].v >> zz[i].sum;
	sort(zz, zz + m , cmp);
	int flag = 0;
	for(int i=0;i<m;i++)
	{
		int s1 = zz[i].u;
		int s2 = zz[i].v;
		if (find(s1) == find(s2))
		{
			cout << zz[i].sum << '\n';
			flag = 1;
			break;
		}
		unionn(s1, s2 + n);
		unionn(s2, s1 + n);
	}
	if (flag == 0)cout << "0" << '\n';
	return 0;
}

B DP
转移方程???
C KMP

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 100; 
char a[N],b[N],ans[N];
int nx[N];
int n, m;
int l1,l2;
 
void getnext(){
    int k = -1, j = 0;
    nx[0] = -1;
    while(j < m){
        if(k == -1 || b[j] == b[k]) nx[++j] = ++k;
        else k = nx[k];
    }
}
int KMP(int st)
{
    int i,j;
    getnext();
    for(i=st,j=0;i<n;i++)
    {
    	while(j>0&&b[j]!=a[i]) j=nx[j];//匹配不成功 跳转到nx
    	if(a[i]==b[j]) j++;
    	if(j==m) return m;
    }
    return j;
}
 
int main()
{
	int t;
	scanf("%d",&t);
	scanf("%s",a);
	n=strlen(a);
	t--;
	int pos=0;
	for(int i=1;i<=t;i++)
	{
		scanf("%s",b);
		m=strlen(b);
		int x=KMP(max(pos-m,0));
		for(int i=x;i<m;i++)
		{
			a[n++]=b[i];
		}
		pos=n;
	}
	a[n]='\0';
	printf("%s\n",a);
}
//贴别人代码 tle就离谱

D KMP 部分
题意 给定字符串 求含多少循环节
eg:abcabc -----2

//如果字符串中存在循环节,则next[len] = (循环节个数 - 1) * 循环节长度
//如果字符串中存在循环节,l-next[l]=循环节长度
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
char s[1000010];
int net[1000010];
void getnext(char* a,int ll)
{
	int i=0,j=-1;
	net[0]=-1;
	while(i<ll)
	{
		if(j==-1||a[i]==a[j])
		{
			net[++i]=++j;
		}
		else j=net[j];
	}
}
int main()
{
	while(scanf("%s",s)&&s[0]!='.')
	{
		int l=strlen(s);
		getnext(s,l);
		int ans=l-net[l];//l-next[l]=循环节长度
		if(l%ans==0)printf("%d\n",l/ans);
		else printf("1\n");//不存在循环节时
	}
	return 0;
}

G 博弈

二、知识积累

1.并查

2.kmp

总结

记得补完

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值