Acwing
基础算法
快速排序模板
选定分界点,可以是l,r,l+r/2等
维护数组 使得分界点左边都<=分界点,右边都>=分界点
递归处理左右两边数组
代码实现如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5+10;
int n, m, k, t;
//快速排序
void quick_sort1(int q[], int l, int r){
//边界不满足左边小,直接返回
if (l >= r) return;
//第一步,确定边界
//tips1:由于i和j都是先自减或自增后判断,初始时i、j往边界两端扩一步
int i = l - 1, j = r + 1, x = q[l];
//第二步,划分区间,使得一边小于x,一边大于x;
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j) swap(q[i], q[j]);
}
//第三步,递归处理两边
quick_sort1(q, l, j), quick_sort1(q, j + 1, r);
}
int main(){
ios;
int a[N];
scanf("%d",&n);//scanf比cin快哦
for(int i = 0;i < n;i ++){
scanf("%d",&a[i]);
}
quick_sort1( a, 0, n - 1);
for(int i = 0;i < n;i ++){
printf("%d ",a[i]);
}
return 0;
}
快速选择模板(第k大的数)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5 + 10;
int n, m, k, t;
int q[N];
int quick_sort(int l,int r,int k){
if(l == r) return q[l];
int x = q[l],i = l - 1, j = r + 1;
while (i < j){
while (q[++ i] < x);//
while (q[-- j] > x);//这里两处漏了分号 ,一直报错没发现,人麻了
if(i < j) swap (q[i] , q[j]);
}
int lenleft = j - l + 1;
if(k <= lenleft) return quick_sort(l, j, k);
else return quick_sort(j + 1, r, k - lenleft);
}
int main(){
ios;
cin >> n >> k;
for(int i = 0;i < n;i ++){
cin >> q[i];
}
cout << quick_sort(0,n - 1,k);
return 0;
}
归并排序
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e6 + 10;
int n, m, k, t;
int q[N];
int tmp[N];//辅助数组,与快排不同的一点
void mergesort(int q[], int l ,int r){
if(l == r) return ;//一个数不用比
int mid = (l + r) >> 1;
//递归
mergesort(q, l, mid);mergesort(q, mid + 1, r);
int k = 0,i = l,j = mid + 1;
//两数组比较合并
while (i <= mid && j <= r){
if(q[i] <= q[j]) tmp[k ++] = q[i ++];
else tmp[k ++] = q[j ++];
}
//把剩余的数直接放最后面
while (i <= mid) tmp[k ++] = q[i ++];
while (j <= r) tmp[k ++] = q[j ++];
for(int i = l, j = 0;i <= r;i ++ ,j ++ ) q[i] = tmp[j];//注意别写成i = 0了
}
int main(){
ios;
cin >> n;
for(int i = 0 ;i < n;i ++) cin >> q[i];
mergesort(q,0,n-1);
for(int i = 0;i < n;i ++) cout << q[i] << " ";
return 0;
}
逆序对数量(归并排序的应用)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e6 + 10;
int n, m, k, t;
int q[N];
int tmp[N];//辅助数组,与快排不同的一点
ll mergesort(int q[], int l ,int r){
if(l == r) return 0;
int mid = (l + r) >> 1;
ll res = mergesort(q, l, mid) + mergesort(q, mid + 1, r);
int k = 0,i = l,j = mid + 1;
while (i <= mid && j <= r){
if(q[i] <= q[j]) tmp[k ++] = q[i ++];
else {
tmp[k ++] = q[j ++];
res += mid - i + 1;//主要区别
}
}
while (i <= mid) tmp[k ++] = q[i ++];
while (j <= r) tmp[k ++] = q[j ++];
for(int i = l, j = 0;i <= r;i ++ ,j ++ ) q[i] = tmp[j];//注意别写成i = 0了
return res;
}
int main(){
ios;
cin >> n;
for(int i = 0 ;i < n;i ++) cin >> q[i];
cout << mergesort(q,0,n-1) << endl;
// for(int i = 0;i < n;i ++) cout << q[i] << " ";
return 0;
}
高精度加法
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e6 + 10;
int n, m, k, t;
vector<int> add(vector<int> &A,vector<int> &B){//int &a意思是定义一个引用 //引用相当于指针再取值 他和被引用的变量都是表示同一块内存
vector<int> C;
int tmp = 0;//进位
for(int i = 0;i < A.size() || i < B.size();i ++){
if(i < A.size()) tmp += A[i];
if(i < B.size()) tmp += B[i];
C.push_back(tmp % 10);
tmp /= 10;
}
if(tmp) C.push_back(tmp);
return C;
}
int main()
{
ios;
string a,b;
vector<int> A,B;
cin >> a >> b;
for(int i = a.size() - 1;i >= 0;i --) A.push_back(a[i] - '0');
for(int i = b.size() - 1;i >= 0;i --) B.push_back(b[i] - '0');
auto C = add(A,B);
for(int i = C.size() - 1;i >= 0;i --) cout << C[i];
return 0;
}
高精度减法
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e6 + 10;
int n, m, k, t;
bool cmp(vector<int> &A,vector<int> &B){
if(A.size() != B.size()) return A.size() > B.size();
else{
for(int i = A.size() - 1;i >= 0;i --)
if(A[i] != B[i]) return A[i] > B[i];
return true;
}
}
//主体部分
vector<int> sub(vector<int> &A,vector<int> &B){
vector<int> c;
int tmp = 0;
for(int i = 0;i < A.size();i ++){//tmp表示借位
tmp = A[i] - tmp;
if(i < B.size()) tmp -= B[i];
c.push_back((tmp + 10) % 10);
if(tmp < 0) tmp = 1;
else tmp = 0;
}
while (c.size() > 1&&c.back() == 0) c.pop_back();//去除前导零,>1是因为只有一个0的情况要输出0
return c;
}
int main()
{
ios;
string a,b;
vector<int> A,B;
cin >> a >> b;
for(int i = a.size() - 1;i >= 0;i --) A.push_back(a[i] - '0');
for(int i = b.size() - 1;i >= 0;i --) B.push_back(b[i] - '0');
auto C = sub(A,B);
if(cmp(A,B)){
auto C = sub(A,B);
for(int i = C.size() - 1;i >= 0;i --) cout << C[i];
}else{
auto C = sub(B,A);
cout << "-";
for(int i = C.size() - 1;i >= 0;i --) cout << C[i];
}
return 0;
}
数的范围(二分)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e6 + 10;
int n, m, k, t;
int q[N];
int main(){
cin >> n >> m;
for(int i= 0 ;i < n ;i ++){
cin >> q[i];
}
while(m --){
int x;
cin >> x;
int l = 0,r = n - 1;
while(l < r){
int mid = l + r >> 1;
if(q[mid] >= x) r = mid;
else l = mid + 1;
}
if(q[l] != x) cout << "-1 -1" << endl;
else{
cout << l << " ";
int l = 0, r = n - 1;
while(l < r){
int mid = l + r + 1 >> 1;//different,防止更新后还是[l,r]造成死循环
if(q[mid] <= x) l = mid;//即取l = mid时mid = (l + r + 1)/2,r = mid 时mid = (l + r)/2
else r = mid - 1;
}
cout << l << endl;
}
}
}
//数的三次方根(浮点二分)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e6 + 10;
int n, m, k, t;
ll a[200010], b[200010], c[200010], cnt[200010];
int main(){
double x;
cin >> x;
double l = -10000,r = 10000;
while (r - l > 1e-8){
double mid = (l + r) / 2;
if(mid * mid * mid >= x) r = mid;
else l = mid;
}
printf("%lf\n",l);
return 0;
}
计算二进制中 1 的个数(位运算应用,重点!!!!)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 100010;
int n, m, k, t;
int lowbit(int x){
return x & -x;
}
int main()
{ //x & -x = x & (~x + 1) // lowbit(x)运算,返回x的最后一位
//应用,统计1的个数
cin >> n;
while(n --){
int x;
cin >> x;
int res = 0;
while(x) x -= lowbit(x),res ++;//减去x最后一位1
cout << res << " ";
}
return 0;
}
补充知识
n >> k & 1 求二进制第 k 位数字
前缀和 子矩阵和(略)
差分&差分矩阵
#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> PII;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5 + 10,M = 1e5+10;
int n, m, k, t;
int a[N], b[N];
void insert(int l,int r,int c){
b[l] += c;
b[r + 1] -= c;//[l,r]中间只用b[l]+c后面都会加c,最后r+1要减回去
}
int main()
{
ios;
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
for (int i = 1; i <= n; i++)
{
b[i] = a[i] - a[i - 1];
}
while (m--)
{
int l, r, c;
cin >> l >> r >> c;
// b[l] += c;
// b[r + 1] -= c;
insert(l,r,c);
}
int sum = b[0];
for (int i = 1; i <= n; i++)
{
sum += b[i];
cout << sum << ' ';
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> PII;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1000 + 10,M = 1e5+10;
int n,m,k,t;
int a[N][N], b[N][N];
int q;
int main()
{
cin >> n >> m >> q;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
scanf("%d", &b[i][j]);
}
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
a[i][j] = b[i][j] - b[i - 1][j] - b[i][j - 1] + b[i - 1][j - 1];
}
}
while (q--)
{
int x1, y1, x2, y2, c;
cin >> x1 >> y1 >> x2 >> y2 >> c;
a[x1][y1] += c;
a[x2 + 1][y1] -= c;
a[x1][y2 + 1] -= c;
a[x2 + 1][y2 + 1] += c;
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
b[i][j] = b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1] + a[i][j];
cout << b[i][j] << ' ';
}
cout << endl;
}
return 0;
}
双指针算法
1.最长连续不重复子序列
#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> PII;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5 + 10,M = 1e5+10;
int n, m, k, t;
int a[N],s[N];
int main()
{
cin >> n;
for(int i = 0;i < n;i ++){
cin >> a[i];
}
int res = 0;
for(int i = 0,j = 0;i < n;i ++){
s[a[i]] ++;
while(s[a[i]] > 1){
s[a[j]] --;
j ++;
}
res = max(res , i - j + 1);
}
cout << res << endl;
return 0;
}
// 双指针算法
//for(int i = 0,j = 0;i < n;i ++){
// while(j < i && check(i,j) ) j ++;
// // 每道题具体逻辑
// }
2.数组元素目标和
#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> PII;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5 + 10,M = 1e5+10;
int n, m, k, t;
int a[N],b[N];
int main()
{
cin >> n >> m >> t;
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
for (int i = 0; i < m; i++)
{
scanf("%d", &b[i]);
}
for (int i = 0, j = m - 1; i < n; i++)
{
while (j >= 0 && a[i] + b[j] > t)
j--;
if (a[i] + b[j] == t)
cout << i << ' ' << j;
}
return 0;
}
3.判断子序列
#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> PII;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5 + 10,M = 1e5 + 10;
int n, m, k, t;
int a[N],b[N];
int main(){
cin >> n >> m;
for(int i = 0;i < n;i ++) scanf("%d",&a[i]);
for(int j = 0;j < m;j ++) scanf("%d",&b[j]);
int i = 0,j = 0;
while(i < n && j < m)
{
if(a[i]==b[j])i ++,j ++;
else j ++;
}
if(i == n) cout<<"Yes";
else cout<<"No";
return 0;
}
离散化(区间和)
#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 3e5 + 10;
int n, m, k, t;
int a[N],s[N];
vector<int> alls;
vector<pii> add,q;
int find (int x){
int l = 0,r = alls.size() - 1;
while(l < r){
int mid = l + r >> 1;
if(alls[mid] >= x) r = mid;
else l = mid + 1;
}
return r + 1;
}
void work()
{
cin >> n >> m;
for(int i = 0;i < n;i ++){
int x,c;
cin >> x >> c;
add.push_back({x,c});
alls.push_back(x);
}
for(int i = 0;i < m;i ++){
int l,r;
cin >> l >> r;
q.push_back({l,r});
alls.push_back(l);
alls.push_back(r);
}
//离散化x,l,r
//去重(离散化核心:去重加二分查找)
sort(alls.begin(),alls.end());
alls.erase(unique(alls.begin(),alls.end()),alls.end());
//处理插入
for(auto it : add){
int x = find(it.first);
a[x] += it.second;
}
//预处理前缀和
for(int i = 1;i <= alls.size();i ++){
s[i] = s[i-1] + a[i];
}
//询问
for(auto it : q){
int l = find(it.first),r = find(it.second);
cout << s[r] - s[l - 1] << endl;
}
}
int main()
{
ios;
int T = 1;
//cin >> T;
while(T --){
work();
}
return 0;
}
区间合并
#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> PII;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5 + 10,M = 1e5+10;
int n, m, k, t;
int a[N],s[N];
int l, r;
vector<PII> segs;
void merge(vector<PII> &segs)
{
vector<PII> res;
sort(segs.begin(), segs.end());
int st = -2e9, ed = -2e9;//数据范围是10^9
for (auto seg : segs)
{
if (ed < seg.first)
{
if (st != -2e9)
res.push_back({st, ed});
st = seg.first, ed = seg.second;
}
else
ed = max(ed, seg.second);
}
if (st != -2e9)//防止输入数组的没有区间
res.push_back({st, ed});//遍历完最后还更新了一次st和ed(最后一组),别忘了把这个加进去
segs = res;
}
int main(){
cin >> n;
for (int i = 0; i < n; i ++){
cin >> l >> r;
segs.push_back({l, r});
}
merge(segs);
cout << segs.size() << endl;
return 0;
}
数据结构
单链表
#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 3e5 + 10;
int n, m, k, t;
int head,e[N],ne[N];//head表示头结点
int idx;
// void init(){
// head = -1;
// idx = 0;//如果这样的话,第k个插入的数下标为k-1
// }
// void hdinsert(int x){//头插
// e[idx] = x;
// ne[idx] = head;
// head = idx ++;
// }
void init(){
ne[0] = -1;//e[0] = 0,但是没意义,最后不输出就行
idx = 1;//这样的话就把合并了两种插入模式
}
//插在下标为 k 的这点后面
int insert(int k,int x){
e[idx] = x;
ne[idx] = ne[k];
ne[k] = idx ++;
}
//下标为 k 的这点后面的一个点删掉,这题删掉点idx不变(一般不管)
int remove(int k){
//if(k == 0) head = ne[head];//如果合并了两种插入方法就不用考虑这个情况了
ne[k] = ne[ne[k]];
}
void work()
{
init();
cin >> n;
char ss;
while(n --)
{
int x, k;
cin >> ss;
if(ss == 'H')cin >> x,insert(0,x);
else if(ss == 'I')cin >> k >> x,insert(k,x);
else cin >> k,remove(k);
}
k = ne[0];
while(k != -1)
{
cout << e[k] << ' ';
k = ne[k];
}
}
int main()
{
ios;
int T = 1;
//cin>> T;
while(T --){
work();
}
return 0;
}
双链表
#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 3e5 + 10;
int n, m, k, t;
int v[N], l[N], r[N], idx;//用数组来分别表示值和下标更加方便
int x;
string str;
void init()//初始化
{
r[0] = 1;
l[1] = 0;// 0 1代表恒定不变的头节点和尾节点(哑节点)
idx = 2;// 0 1已经占用了2个 idx,故 idx 从 2 开始
}
void insert(int k, int x)
{
v[idx] = x;
l[idx] = k;
r[idx] = r[k];
l[r[k]] = idx;
r[k] = idx ++;
}
void remove(int k)//把第 k 个插入的节点删除
{
r[l[k]] = r[k];
l[r[k]] = l[k];
}
void work()
{
init();
cin >> n;
while(n --)
{
cin >> str;
if(str == "L")cin >> x,insert(0,x);
else if(str == "R")cin >> x,insert(l[1],x);
else if(str == "IR")cin >> k >> x,insert(k + 1,x);
else if(str == "IL")cin >> k >> x,insert(l[k + 1],x);
else cin >> k,remove(k + 1);
}
k = r[0];
while(k != 1)
{
cout << v[k] << ' ';
k = r[k];
}
}
int main()
{
ios;
int T = 1;
//cin >> T;
while(T --){
work();
}
return 0;
}
表达式求值(栈的应用)
`#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5 + 10;
int n, m, k, t;
stack<int> num;
stack<char> op;
void eval()
{
int b = num.top();
num.pop();
int a = num.top();
num.pop();
char c = op.top();
op.pop();
if(c=='+')a += b;
else if(c=='-')a -= b;
else if(c=='*')a *= b;
else a /= b;
num.push(a);
}
void work()
{
unordered_map<char,int> pr{{'+',1},{'-',1},{'*',2},{'/',2}};
string ss;
cin >> ss;
for(int i = 0;i < ss.size();i ++){
auto c = ss[i];
if(isdigit(c)){
int x = 0,j = i;
while(j < ss.size()&&isdigit(ss[j]))
x = x * 10 + ss[j ++] - '0';
i = j - 1;
num.push(x);
}
else if(ss[i]=='(') op.push(ss[i]);
else if(ss[i]==')'){
while(op.top()!='(') eval();
op.pop();
}
else{
while(op.size()&&pr[op.top()] >= pr[ss[i]])//判断优先级
eval();
op.push(ss[i]);
}
}
while(op.size()) eval();
cout << num.top();
}
int main()
{
ios;
int T = 1;
//cin >> T;
while(T --){
work();
}
return 0;
}
数组模拟队列
#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5 + 10;
int n, m, k, t;
int q[N],hh = 0,tt = -1;//hh队头,tt队尾
int main(){
string str;
cin >> n;
while(n --)
{
cin >> str;
int x;
if(str == "push")cin >> x,q[++ tt]=x;
else if(str == "pop")hh ++;
else if(str == "empty")
if(tt < hh)cout << "YES" << endl;
else cout << "NO" << endl;
else cout << q[hh] << endl;
}
return 0;
}
单调栈
#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5 + 10;
int n, m, k, t;
stack<int> s;
int main(){
cin >> n;
while (n --)
{
int x;
cin >> x;
while (!s.empty() && x <= s.top())
s.pop();
if (s.empty())
cout << -1 << " ";
else
cout << s.top() << " ";
s.push(x);
}
return 0;
}
滑动窗口(单调队列/双端队列)
#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e6 + 10;
int n, m, k, t;
int s[N];
deque<int> q;
int main(){
cin >> n >> k;
for(int i = 0;i < n;++ i)cin >> s[i];
for(int i = 0;i < n;++ i)
{
while(!q.empty() && s[i] <= s[q.back()]) q.pop_back();
q.push_back(i);
if(q.front() + k == i) q.pop_front();
if(i >= k - 1) cout << s[q.front()] << " ";
}
cout << endl;
q.clear();
for(int i = 0;i < n;++ i)
{
while(!q.empty() && s[i] >= s[q.back()]) q.pop_back();
q.push_back(i);
if(q.front() + k == i) q.pop_front();
if(i >= k - 1)cout << s[q.front()] << " ";
}
return 0;
}
KMP算法
#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
typedef long long ll;
typedef pair<int,int> pii;
#define endl '\n'
#define ios ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x7fffffff
const int N = 1e5 + 10;
int n, m, k, t;
int main(){
string s, ss;
cin >> m >> ss >> n >> s;
//求ne[]
int ne[N] = {0};
for (int i = 1, j = 0; i < m; i++)
{
while (j && ss[i] != ss[j])
j = ne[j - 1];
if (ss[i] == ss[j])
j++;
ne[i] = j;
}
for (int i = 0, j = 0; i < n; i++)
{
while (j && s[i] != ss[j])//j的含义是j没通过next跳到初始位置(也就是说没有重新开始匹配)
j = ne[j - 1];
if (s[i] == ss[j])
j++;
if (j == m)
cout << i - j + 1 << ' ';
}
return 0;
}
搜索与图论
DFS
void dfs(int step) //步长
{
if(/*跳出循环的条件*/){
return; //return十分关键,否则循环将会无法跳出
}
/*函数主体
对功能进行实现*/
for(/*对现有条件进行罗列*/){
if(/*判断是否合理*/){
//将条件修改
dfs(/*新的step*/)
/*!重中之重,当跳出那层循环后将数据全部归位*/
}
}
}
//例如,acwing排列数字
const int N = 10;
int a[N],n;
bool st[N];
void dfs(int x)
{
if(x == n)
{
for(int i = 0;i < n;i++)cout << a[i] << ' ';
cout << endl;
return;
}
for(int i = 1;i <= n;i++)
{
if(!(st[i]))
{
a[x] = i;
st[i] = true;
dfs(x+1);
st[i] = false;
}
}
}
int main()
{
cin >> n;
dfs(0);
return 0;
}
DFS 矩阵 模板
int f[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; //用于判断下一步怎么走向几个方向走就是几个数据
void dfs(int x,int y){ //进入点的坐标
if(/*跳出循环的条件*/){
/*作出相应操作*/
return; //不要忘了return
}
for(int i=0;i</*f的长度*/;i++){
int x0=x+f[i][0];
/*此处是更新点的坐标,注意是直接让原来的点加上这个数据,不是直接等于*/
int y0=y+f[i][1];
if(/*用新坐标x0,y0判断是否符合条件*/){
dfs(x0,y0); //用新的坐标进行递归
}
}
}
BFS
AcWing 844. 走迷宫
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
typedef long long ll;
typedef pair<int,int>PII;
int g[N][N],d[N][N];
int n, m;
queue <PII> q;
int bfs()
{
memset(d,-1,sizeof d);
d[0][0] = 0;
q.push({0,0});
int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};
while(!q.empty())
{
auto t = q.front();
q.pop();
for(int i = 0;i < 4;i++)
{
int x = t.first + dx[i],y = t.second + dy[i];
if(x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1)
{
d[x][y] = d[t.first][t.second]+1;
q.push({x,y});
}
}
}
return d[n-1][m-1];
}
int main()
{
cin >> n >> m;
for(int i = 0;i < n;i++)
{
for(int j = 0;j < m;j++)
{
cin >> g[i][j];
}
}
cout << bfs() << endl;
return 0;
}
AcWing 845. 八数码
#include <bits/stdc++.h>
using namespace std;
int bfs(string s)
{
string sl = "12345678x";
queue<string>q;
unordered_map<string,int>d;
q.push(s);
d[s] = 0;
int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};
while(q.size())
{
auto t = q.front();
q.pop();
int distance = d[t];
if(t == sl) return distance;
int k = t.find('x');
int x = k/3,y = k%3;
for(int i = 0;i < 4;i++)
{
int a = x+dx[i],b = y+dy[i];
if(a >= 0 && a < 3 && b < 3 && b >= 0)
{
swap(t[k],t[a*3+b]);
if(!d.count(t))
{
d[t] = distance+1;
q.push(t);
}
swap(t[k],t[a*3+b]);
}
}
}
return -1;
}
int main ()
{
string s;
for(int i = 0;i < 9;i++)
{
char c;
cin >> c;
s += c;
}
cout << bfs(s) << endl;
return 0;
}
本文作者:Go1NgZCY
本文链接:https://www.cnblogs.com/going-zcy/p/18062145
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步