必须记忆的算法——记忆笔记

 高效素数打表——欧拉打表

s[i+1].find(s[i])==s[i+1].npos//  npos  表示不存在
#include<iostream>
#define maxn 100000
#define maxl 1000000
using namespace std;
int prime[maxn];
bool vis[maxl];
void get_prime(){//线性时间筛法——欧拉筛法
	int cnt=0;
	int i,j;
	for(i=2;i<maxl;i++){
		if(!vis[i]){
			prime[cnt++]=i;vis[i]=true;
		}
		for(j=0;j<cnt;j++){
			if(i*prime[j]>maxl)break;
			vis[i*prime[j]] =true;
			if(i%prime[j]==0) break; 
		}
	}
}
int main(){
	get_prime();
	for(int i=0;i<100;i++) cout<<prime[i]<<endl;
	return 0;
}

最长对称子序列——偶数,奇数

#include<iostream>
#include<algorithm>
#include<set>
#include<cstring>
using namespace std;
int main() {
	string a;
	while (getline(cin, a)) {
		int l = a.length();
		int len = 0;
		for (int i = 0; i < l; i++) {
			for (int j = 0; i - j >= 0 && i + j < l; j++) {
				if (a[i - j] != a[i + j]) break;
				if (2 * j + 1 > len) len = 2 * j + 1;
			}
			for (int j = 0; i - j >= 0 && i + j <= l; j++) {
				if (a[i - j] != a[i + j + 1]) break;
				if (2 * j + 2 > len) len = 2 * j + 2;
			}
		}
		cout << len << endl;
	} return 0;
}

最长子序列

#include<iostream>
using namespace std;
int maxs(const int a[], int n) {
	int thissum, maxsum, j;
	thissum = maxsum = 0 ;
	for (j = 0; j < n; j++) {
		thissum += a[j];
		if (thissum > maxsum) maxsum = thissum;
		else if (thissum < 0) thissum = 0;
	}
	return maxsum;
}
int main() {
	int a[1000];
	int n;
	cin >> n;
	for (int i = 0; i < n; i++) cin >> a[i];
	int maxss=maxs(a, n);
	cout << maxss << endl;
	system("pause");
	return 0;
}

kmp 算法 ——两个字符串 匹配  输出 起始 index

#include<iostream>
using namespace std;
const int maxl = 1000000;
const int maxn = 100000;
int a[maxl], b[maxn];
int n, m, f;//m 模板长度 n 匹配串长度
int nex[maxn];
void get_next() {
	int i = 0; int j = -1;
	nex[0] = -1;
	while (j < n) {
		if (j == -1 || a[i] == b[j])nex[++i] = ++j;
		else j = nex[j];
	}
}
void kmp() {
	int i =0, j =0;

	get_next();
	while (i < m) {
		if (j == -1 || a[i] == b[j])
		{
			i++; j++;
		}
		else j = nex[j];
		if (j == n) {
			cout << i - n + 1 << endl;
			f = 0;
			break;
		}
	}
}
int main(){
	ios::sync_with_stdio(false);
	int t;
	cin >> t;
	while (t--) {
		f = 1;
		for (int i = 0; i < m; i++) cin >> a[i];
		for (int i = 0; i < n; i++) cin >> b[i];
		kmp();
		if (f) cout << "-1" << endl;
	}return 0;
}

欧几里得算法————求两个数的最大公因数

unsigned int gcd(int x, int y) {//循环实现
	unsigned int rem;
	while (y > 0) {
		rem = x % y;
		x = y;
		y = rem;
	}
	return x;
}

int gcd1(int x, int y) {//递归实现
	return y == 0 ? x : gcd(y, x%y);
}

最小公倍数 ——借助gcd()

int g(int x, int y) {
	return x / gcd(x, y)*y;
}// 先除法后乘法 防止数据溢出

 

对分查找————排好序的数组中查找某一元素T

int BinarySearch(const ElementType a[],ElwmentTpye T,int n){
	int low,mid,high;
	low=0;
	high=n-1;
	while(low<=high){
		mid=(low+high)/2;
		if(a[mid]<x){
			low=mid+1;
		}else if(a[mid]>x){
			high=mid-1;
		}else return mid;/* found*/
	}
	return -1;/*notfound*/
}

快速幂 

long int pow(long int x,long int n){
	if(n==0) return 1;
	if(n==1) return x;
	if(n%2){//奇数个 
		return pow(x*x,n/2)*x;
	}else return pow(x*x,n/2);//偶数个 
}

两点间的最短路径——固定一点到其余所有点的最短路径(Dijkstra算法)(没有负边的情况)

#include<iostream>
#include<sstream>
using namespace std;
#define M 210
#define INF 0x3f3f3f 
int arr[M][M], vis[M], dis[1010];// arr 路径 // vis 标记数组 dis  距离
int n, m;
void Dijkstra(int src) {//一点(src) 到 其余所有点的最短路径
	for (int i = 0; i < n; i++) {
		vis[i] = 0; dis[i] = arr[src][i];
	}
	int temp, k;
	vis[src] = 1; dis[src] = 0;
	for (int i = 0; i < n; i++) {
		temp = INF;
		for (int j = 0; j < n; j++) {
			if (!vis[j] && temp > dis[j]) {
				temp = dis[j];
				k = j;
			}
		}

		vis[k] = 1;
		for (int j = 0; j < n; j++) {
			if (!vis[j] && dis[j] > arr[k][j] + dis[k]) dis[j] = arr[k][j] + dis[k];
		}
	}
}
void work() {
int s, t, u, v, w;
	while (cin>>n>>m) {
		for (int i = 0; i < n; i++) for(int j=0;j<n;j++) arr[i][j] = INF;//初始化
		for (int i = 0; i < m; i++) {
			cin >> u >> v >> w;
			if(arr[u][v]>w) arr[u][v] = arr[v][u] = w;//输入 ——输入最短路径 (可能路不只有一条)
		}
		cin >> s >> t;// 需要 求得 s 到 t(也可以是其他值) 的最短路径
		Dijkstra(s);// 
		if (dis[t] != INF) cout<< dis[t]; else cout << "-1";
		puts("");
	}
}
int main() {
	work();
	
	system("pause");
	return 0;
}
//Dijkstra 算法的另一种写法
#include<iostream>
#include<cmath>
#include<math.h>
#include<sstream>
#include<cstring>
using namespace std;
#define M 110
#define INF 0x3f3f3f
int arr[M][M], vis[M], dis[1010];//三个数组都需要初始化
/*
arr数组 初始化 目的: 保证在输入的 两地之间 只记录最短的距离 (可能两地有不止一条路)
vis  标记是否被读取 走过的路不再重复
dis  初始为最远  
*/
int n, m;// n 顶点数
int min(int x, int y) {
	return x < y ? x : y;
}
void Dijkstra(int src) {//一点 到 其余所有点的最短路径
	memset(vis, 0, sizeof(vis));
		memset(dis, INF, sizeof(dis));
		dis[src] = 0;
		while (true) {
			int v = -1;
			//从尚未选择的顶点中选一个距离最小的点
			for (int i = 1; i <= n; i++) {
				if (!vis[i] && (v ==-1 || dis[i] < dis[v])) v = i;
			}
			if (v == -1) break;
			vis[v] = 1;
			for (int i = 1; i <= n; i++) {
				dis[i] = min(dis[i],dis[v] + arr[v][i]);
			}
		}
}

void work() {
int s, t, u, v, w;
	while (cin>>n>>m) {
		if (m == 0 && n == 0) break;
		for (int i = 1; i <= n; i++) for(int j=1;j<=n;j++) arr[i][j] = INF;
		for (int i = 0; i < m; i++) {
			cin >> u >> v >> w;
			if(arr[u][v]>w) arr[u][v] = arr[v][u] = w;
		}
		s = 1; t = n;
		Dijkstra(s);
		 cout << dis[t];
		puts("");
	}
}
int main() {
	work();
	
	system("pause");
	return 0;
}

最小生成树——用于求取一棵树上最近的联通距离(eg: 连接所有村庄的电线最短长度)

#include <iostream>
#include<math.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 101;

int n; //节点数
int mp[N][N];//地图
int dis[N];//存储距离
int vis[N];//标记

int min(int x, int y) {
	return x < y ? x : y;
}
int prime(int s) //传进起始点
{

	for (int i = 0; i < n; i++) {
		dis[i] = inf;
		vis[i] = 0;
	}
	dis[s] = 0;
	int res = 0;
	while (true) {
		int v = -1;
		for (int i = 0; i < n; i++) if (!vis[i] && (v == -1 || dis[i] < dis[v])) v = i;;
		if (v == -1) break;
		vis[v] = true;
		res += dis[v];
		for (int i = 0; i < n; i++) {
			dis[i] = min(dis[i], mp[v][i]);
		}
	}return res;
}

void work() {
	while (cin >> n) {
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++) { cin >> mp[i][j]; if (!mp[i][j]) mp[i][j] = inf; }
		int num = prime(0);
		cout << num << endl;
	}
}
int main() {
	work();
	system("pause");
	return 0;
}
//法二
void prim(){
	int i,j,d[MAXV],vis[MAXV],mi,v;
	for(i=1;i<=n;i++){
		d[i]=map[1][i];
		vis[i]=0;
	}
	for(i=1;i<=n;i++){
		mi=inf;
		for(j=1;j<=n;j++)
			if(!vis[j] && d[j]<mi){
				mi=d[j];
				v=j;
			}
		vis[v]=1;
		for(j=1;j<=n;j++)
			if(!vis[j] && d[j]>map[v][j])
				d[j]=map[v][j];
	}
	for(d[0]=0,i=1;i<=n;i++) d[0]+=d[i];
 
	printf("%d\n",d[0]);
}
// 法三
const int inf = 0x3f3f3f3f;
const int N = 30;

int n; //节点数
int mp[N][N];//地图
int dis[N];//存储距离
int vis[N];//标记

int prime(int s) //传进起始点
{
    int sum = 0;  //权值总和

    for(int i = 0;i < n;i ++)  //初始化起始点到各点的距离
        dis[i] = mp[s][i];

    vis[s] = 1;      

    for(int i = 1;i <= n - 1;i ++)
    {
        //  n - 1次迭代
        int minn = inf;
        int p;
        for(int j = 0;j < n;j ++)       //找到距离最小的点
        {
            if(!vis[j] && dis[j] < minn)
                minn = dis[j], p = j;
        }

        vis[p] = 1;    

        sum += minn;        //加上边权值

        for(int j = 0;j < n;j ++)  //松弛操作
        {
            if(!vis[j] && dis[j] > mp[p][j])
                dis[j] = mp[p][j];
        }
    }
    return sum;
}

memset 的使用

#include<cstring>
//memset赋值时以 单字节赋值
//memset使用时要千万小心,在给char以外的数组赋值时,只能初始化为0或者-1。

char a[10];
int num[10];
memset(a,'A',sizeof(a));//是可以的  效果是全部复制为‘A’
memset(num,0,sizeof(num));//也可以
memset(num,1,sizeof(num));//不可以  
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值