头文件<string.h>
1 | strcmp(str1,str2); |
比较两个字符串,如果两个字符串相等,则返回0.
若str1大于str2(比较第一个不相等的字符的ASCII码)返回一个正数(不一定是1)
若str1小于str2(比较第一个不相等的字符的ASCII码)返回一个负数(不一定是-1)
1 | strncmp(str1,str2,n); |
比较两个字符串的前n个字符,其他与strcmp同理
1 | stricmp(str1,str2); |
忽略两个字符串中的大小写,即对大小写不敏感.
n:节点个数
m:边的个数
n^2~m (同一数量级)
稠密图: 用邻接矩阵存储d[t][j]表示从t到j的权重
1 | int g[N][N];//权重 |
n~m (同一数量级)
稀疏图: 用邻接表存储
1 | #include<iostream> |
松弛操作
两层循环
1 | //N为最大节点的个数 |
目的是实现三角不等式即
1 | dist[b]<=dist[a]+w; |
1 | const int N=1e5+5; |
1 | void spfa(){ |
1 | const int INF=1e9; |
1 | int e[maxn],ne[maxn]; |
1 | int idx; |
调用函数
1 | add(r[0],x);//在链表的最左端插入值为x的节点 |
栈顶插入 栈顶弹出 判断是否为空 查询栈顶元素
1 | int stk[maxn]; |
队尾插入 队头弹出 判断是否为空 查询队头元素
1 | int q[maxn]; |
输出左侧第一个比当前数字小的数 没有输出-1
1 | const int maxn=1e5+10; |
主函数
1 | for(int i=0;i<n;i++){ |
有一个大小为 k 的滑动窗口,它从数组的最左边移动到最右边且每次向右移动一个位置,分别输出窗口的最大值和最小值.
初始化并读入到a[]中
1 | const int maxn=1e6+10; |
求最小值
1 | for(int i=0;i<n;i++){//i指向窗口的末端 |
求最大值
1 | for(int i=0;i<n;i++){//i指向窗口的末端 |
初始化并输入
1 | const int N=1e5+10,M=1e6+10; |
求next[]
1 | ne[1]=0; |
KMP算法
1 | for(int i=1,j=0;s[i];i++){ |
I x 向集合中插入一个字符串 x
Q x 询问一个字符串在集合中出现了多少次
初始化
1 | const int maxn=1e5+10; |
插入操作
1 | void insert(char str[]){ |
查找操作
1 | int query(char str[]){ |
主函数
1 | int n; |
①讲两个集合合并
②询问两个集合是否在一个集合当中
基本原理:每个集合用一棵树来表示.树根的标号就是整个集合的编号.每个节点存储它的父节点.p[x]表示 x 的父节点
1 | //初始化 |
① I x 插入一个数 x;
② PM 输出当前集合中的最小值;(输出堆顶 h[1])
③ DM 删除当前集合中的最小值(数据保证此时的最小值唯一);
④ D k 删除第 k 个插入的数;
⑤ C k x 修改第 k 个插入的数,将其变为 x;
预处理
1 | int n; |
1 | void heap_swap(int a,int b){//堆排列特有的交换方式 |
两个堆的排序函数
1 | void down(int u){//u是节点的序号 寻找三个节点中最小的节点 |
操作实现
1 | if(!strcmp(op,"I")){//插入数x |
1 | const int null=0x3f3f3f3f;//极大值1061109567与INT_MAX同一数量级 且不会溢出 |
1 | int find(int x){//哈希表特有的搜索函数 |
1 | memset(h,0x3f,sizeof(h)); |
1 | const int N=2e5+3; |
1 | void insert(int x){ |
1 | memset(h,-1,sizeof(h));//-1表示链表的末尾 |
判断一个字符串的两个子区间是否完全相等
1 | typedef unsigned long long ULL; |
1 | ULL get(int l,int r){ |
1 | //预处理 |
利用vector存储映射的一组数据
1 | typedef pair<int,int> PII; |
1 | unique函数的原型: |
返回值指向去重后容器中不重复序列的最后一个元素的下一元素
1 | sort(all.begin(),alls.end()); |
1 | int find(int x){ |
1 | for(auto it:add){ |
1 | for(auto it:query){ |
位运算概览
1 | 符号 描述 运算规则 |
1 | cout<<(n>>k&1); |
这里&1判断n是否为奇数
①n为奇数时,对应的二进制数最低位一定为1,&1的结果就是1.
②n为偶数时,相应的最低位为0,n&1的结果就是0.
这里等价于 (n>>k)%2
x&-x
(-x)=~x+1
1 | /* |
对于一个序列 借助两个指针维护一个区间(i与j有单调关系)
1 | for(int i=0;i<n;i++){ |
可将暴力两层嵌套循环O(n^2)优化到O(n)
找出最长的不包含重复数字的连续子序列[l,c]的长度
input 1 2 2 3 5
output 3
1 | int res=0; |
1 | vector<int>::iterator unique(vector<int> &a){ |
调用实现去重操作
1 | sort(a.begin(),a.end()); |
对于一维数组a和数组b
a[i]=b[1]+b[2]+…+b[i];
b[1]=a[1]
b[2]=a[2]-a[1]
··· ···
b[n]=a[n]-a[n-1]
称数组a是数组b的前缀和 数组b是数组a的差分
1 | void insert(int l,int r,int c){//数组b是数组a的差分 b[i]=a[i]-a[i-1] |
对于二维数组a和数组b
a[i][j]=a[i-1][j]+a[i][j-1]-a[i-1][j-1]+b[i][j];
b[1][1]=a[1][1]-a[1][0]-a[0][1]+a[0][0]
b[2][2]=a[2][2]-a[2][1]-a[1][2]+a[1][1]
··· ···
b[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1]
称数组a是数组b的前缀和 数组b是数组a的差分
1 | void insert(int x1,int y1,int x2,int y2,int c){//这样变化后只有含有加上c的子矩阵元素的前缀和才会改变 |
1 | struct node{ |
1 | struct node *head,*p,*q,*t; |
如果这个链表很长,且每个节点的值相同
再插一个相同的值进去会遍历整个链表然后插入到链表尾部 浪费了时间
将大于号改为大于等于
1 | cin>>a; //输入插入的数字 |
1 | t=head; |