AcWing算法基础课-数据结构-队列、单调栈、单调队列、KMP

目录

1、队列

1.1 模板

1.2 例题

2、单调栈

2.1 模板

2.2 例题

3、单调队列

3.1 模板

3.2 例题

4、KMP

4.1 模板

4.2 例题

1、队列

1.1 模板

1)普通队列
// hh 表示队头,tt表示队尾
int q[N], hh = 0, tt = -1;

// 向队尾插入一个数
q[ ++ tt] = x;

// 从队头弹出一个数
hh ++ ;

// 队头的值
q[hh];

// 判断队列是否为空,如果 hh <= tt,则表示不为空
if (hh <= tt)
{

}

2)循环队列
// hh 表示队头,tt表示队尾的后一个位置
int q[N], hh = 0, tt = 0;

// 向队尾插入一个数
q[tt ++ ] = x;
if (tt == N) tt = 0;

// 从队头弹出一个数
hh ++ ;
if (hh == N) hh = 0;

// 队头的值
q[hh];

// 判断队列是否为空,如果hh != tt,则表示不为空
if (hh != tt)
{

}

1.2 例题

题目来源:AcWing
题目链接:AcWing 829. 模拟队列
代码展示:

#include <iostream>

using namespace std;

const int N = 1e5 + 10;

int q[N], hh = 0, tt = -1;

int main()
{
    int m;
    cin >> m;
    
    while (m -- )
    {
        string op;
        cin >> op;
        
        if (op == "push")
        {
            int x;
            cin >> x;
            
            q[ ++ tt] = x;
        }
        else if (op == "pop") hh ++;
        else if (op == "query") cout << q[hh] << endl;
        else
        {
            if (hh <= tt) cout << "NO" << endl;
            else cout << "YES" << endl;
        }
    }
    
    return 0;
}

2、单调栈

2.1 模板

常见模型:找出每个数左边离它最近的比它大/小的数
int tt = 0;
for (int i = 1; i <= n; i ++ )
{
    while (tt && check(stk[tt], i)) tt -- ;
    stk[ ++ tt] = i;
}

2.2 例题

题目来源:AcWing
题目链接:AcWing 830. 单调栈
代码展示:

#include <iostream>

using namespace std;

const int N = 1e5 + 10;

int stk[N], tt = 0;

int main()
{
    int m;
    cin >> m;
    
    while (m -- )
    {
        int x;
        cin >> x;
        
        while (tt && stk[tt] >= x) tt --;
        if (!tt) cout << -1 << " ";
        else cout << stk[tt] << " ";
        
        stk[ ++ tt] = x;
    }
    
    return 0;
}

3、单调队列

3.1 模板

常见模型:找出滑动窗口中的最大值/最小值
int hh = 0, tt = -1;
for (int i = 0; i < n; i ++ )
{
    while (hh <= tt && check_out(q[hh])) hh ++ ;  // 判断队头是否滑出窗口
    while (hh <= tt && check(q[tt], i)) tt -- ;
    q[ ++ tt] = i;
}

3.2 例题

题目来源:AcWing
题目链接:AcWing 154. 滑动窗口
代码展示:

#include <iostream>

using namespace std;

const int N = 1e6 + 10;

int a[N], q[N];


int main()
{
    int n, k;
    cin >> n >> k;
    
    for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]);
    
    int hh = 0, tt = -1;
    for (int i = 0; i < n; i ++ )
    {
        if (hh <= tt && i - k + 1 > q[hh]) hh ++ ;
        
        while (hh <= tt && a[q[tt]] >= a[i]) tt -- ;
        q[ ++ tt] = i;
        
        if (i >= k - 1) printf("%d ", a[q[hh]]);
    }
    
    puts("");
    
    hh = 0, tt = -1;
    for (int i = 0; i < n; i ++ )
    {
        if (hh <= tt && i - k + 1 > q[hh]) hh ++ ;
        
        while (hh <= tt && a[q[tt]] <= a[i]) tt -- ;
        q[ ++ tt] = i;
        
        if (i >= k - 1) printf("%d ", a[q[hh]]);
    }
    
    return 0;
}

4、KMP

4.1 模板

// s[]是长文本,p[]是模式串,n是s的长度,m是p的长度
求模式串的Next数组:
for (int i = 2, j = 0; i <= m; i ++ )
{
    while (j && p[i] != p[j + 1]) j = ne[j];
    if (p[i] == p[j + 1]) j ++ ;
    ne[i] = j;
}

// 匹配
for (int i = 1, j = 0; i <= n; i ++ )
{
    while (j && s[i] != p[j + 1]) j = ne[j];
    if (s[i] == p[j + 1]) j ++ ;
    if (j == m)
    {
        j = ne[j];
        // 匹配成功后的逻辑
    }
}

4.2 例题

题目来源:AcWing
题目链接:AcWing 831. KMP字符串
代码展示:

#include <iostream>

using namespace std;

const int N = 1e5 + 10, M = 1e6 + 10;

int n, m;
char p[N], s[M];
int ne[N];

int main()
{
    cin >> n >> p + 1 >> m >> s + 1;
    
    for (int i = 2, j = 0; i <= n; i ++ )
    {
        while (j && p[i] != p[j + 1]) j = ne[j];
        if (p[i] == p[j + 1]) j ++ ;
        ne[i] = j;
    }
    
    for (int i = 1, j = 0; i <= m; i ++ )
    {
        while (j && s[i] != p[j + 1]) j = ne[j];
        if (s[i] == p[j + 1]) j ++ ;
        if (j == n)
        {
            printf("%d ", i - n);
            j = ne[j];
        }
    }
}

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值