首页 > 其他分享 >E - Stamp

E - Stamp

时间:2023-11-19 16:33:21浏览次数:30  
标签:字符 窗口 Stamp res int vector 字符串

题目链接 : E - Stamp (atcoder.jp)

题意:给定长为n的s串,m的t串,和一个长度为n的x串,问你能否操作任意次数的操作, 每次操作都可以使x中长度为m的存在串变为t,最后使得变为n

赛时没过,赛后有人发了原题,936. 戳印序列 - 力扣(LeetCode),看了很久的题解,发现做法太巧妙了,把字符串转化为(图论)拓扑图,属实想不到, 最后还能求出可以操作哪些位置

思路:因为前面的操作会影响后面的操作,所以要考虑倒推

本文采用类似于拓扑排序的思想。

我们记字母印章长度为 m ,目标字符串长度为 n 。我们拿字母印章在目标字符串上进行滑动,那么在目标字符串中总共将会有 n−m+1 个窗口。另外,我们将逆序操作过程中所得到的各窗口的起始端点值记录在列表 res 中,最后只需将 res 反转即可得到答案。

那么我们可以将本题和拓扑排序的相关概念进行映射:

>「入度」:每个窗口中对应字符不相同的总数,起始默认为 m。当入度为 0 时,说明这个窗口的所有字符都与目标字符串相对应,我们就可以把这个窗口放入到队列(不一定是 vector 的队列,任意容器均可, deque也可以)中。

>「边」:对于目标字符串的每个位置上,有不一致字符的窗口。我们用邻接表的方式存储边,如果一个滑动窗口的某一个字符与目标字符串不一致,那么我们就连一条边。
至此,我们通过拓扑排序,就可以得到最终的结果了:

1.遍历一遍所有的窗口,如果该位置上的字符与目标字符不一致,那么我们在邻接表中连接一条边;相反如果字符一致,那么该窗口的入度减 1。
2.当某个窗口的入度为 0 时,那么这个窗口的所有字符都与目标字符串相对应,我们可以将该窗口的起始端点放入到队列中。
3.将队列中的窗口依次出队,每次出队时,我们在 res 列表中记录该窗口的起始端点。
4.我们可以想象该窗口中的字符全部替换为 '#' ,表示可以匹配任意字符。那么我们可以从邻接表中将之前与该位置不同的窗口的入度都减 1。
5.重复(2),直到队列为空。
6.当队列为空时,判断 res 的长度是否与 n−m+1 相等,相等则完成了拓扑排序;不相等则说明无法印出目标字符串。
 7.如果完成了拓扑排序,那么 res 的长度一定是符合题目要求,我们只需返回逆序的 res 即可(逆序分析)。相反,我们返回一个空容器。最后根据容器大小ac这道题

ac代码

// Problem: E - Stamp
// Contest: AtCoder - Sky Inc, Programming Contest 2023(AtCoder Beginner Contest 329)
// URL: https://atcoder.jp/contests/abc329/tasks/abc329_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>

using namespace std;
using ull = unsigned long long;
using ll = long long;
using PII = pair<int,int>;
#define IOS ios::sync_with_stdio(false),cin.tie(0)
#define endl "\n"
#define pb push_back
const int N=1e5+10;
const int INF=0x3f3f3f3f;
const int mod=998244353;

void solve()
{
    int n, m; cin >> n >> m;
    string s, t; cin >> s >> t;
    vector<vector<int>> g(n);
    vector<int> ind(n - m + 1, m);
    vector<int> q;
    vector<bool> st(n);
    for(int i = 0; i < n - m + 1; i ++)
    {
        for(int j = 0; j < m; j ++)
        {
            if(s[i + j] == t[j])
            {
                ind[i] --;
                if(ind[i] == 0) q.pb(i);
            }
            else
                g[i + j].pb(i);
        }
    }
    vector<int> res;
    while(q.size())
    {
        int u = q.back(); q.pop_back();
        res.pb(u);
        for(int i = 0; i < m; i ++)
        {
            if(st[u + i]) continue;
            st[u + i] = true;
            for(auto &&v : g[u + i])
            {
                ind[v] --;
                if(ind[v] == 0) q.pb(v);//插到u后面,可以改变v窗口的元素
            }
        }
    }
    reverse(res.begin(), res.end());//正确的顺序
    //for(auto it : res) cout << it << ' ';
    if(res.size() < n - m + 1) cout << "No" << endl;
    else cout << "Yes" << endl;
}
int main()
{
        solve();
    return 0;
}

 

标签:字符,窗口,Stamp,res,int,vector,字符串
From: https://www.cnblogs.com/ZouYua/p/17842212.html

相关文章

  • MySQL 8.0 目前仍旧没有解决timestamp时间戳溢出的问题
    在MySQL中,TIMESTAMP列的默认范围是从'1970-01-0100:00:01'到'2038-01-1903:14:07'。如果插入的时间值超出了该范围,MySQL会将其视为无效值,并将其设置为'0000-00-0000:00:00'。在MySQL8.0.35最新版本中,timestamp时间戳溢出的问题目前仍旧没有解决。如下图所示:为了解决这个问题,只......
  • oracle数据库 时间 TIMESTAMP(6)这是什么类型啊 怎么也插不进数据 ,是时间戳类型,参数6
    oracle数据库时间TIMESTAMP(6)这是什么类型啊怎么也插不进数据是时间戳类型,参数6指的是表示秒的数字的小数点右边可以存储6位数字是时间戳类型,参数6指的是表示秒的数字的小数点右边可以存储6位数字,最多9位。解决方法如下:1、时间戳的概念:它是一种时间表示方式,定义为从格林威......
  • timestamp(6)详解 在MySQL中,timestamp是一种时间戳类型。timestamp(6)是timestamp类型
    timestamp(6)详解在MySQL中,timestamp是一种时间戳类型。timestamp(6)是timestamp类型的一个子类型,表示精确到秒后6位小数的时间戳。它占用8个字节存储空间一、什么是timestamp(6)在MySQL中,timestamp是一种时间戳类型。timestamp(6)是timestamp类型的一个子类型,表示精确到秒后6......
  • MySQL timestamp查询
    MySQL是一个常用的关系型数据库管理系统,广泛应用于各个行业的数据存储和处理中。在MySQL中,timestamp是一种常用的数据类型,用于表示日期和时间。本文将介绍如何使用MySQL中的timestamp进行查询操作,并给出相应的代码示例。1.timestamp的概述timestamp是MySQL中的一种日期和时间类......
  • 日期转换工具类:由TimeStamp时间戳转换为日期格式的字符串
    importlombok.extern.slf4j.Slf4j;importorg.apache.commons.lang3.StringUtils;importjava.text.ParseException;importjava.text.SimpleDateFormat;importjava.util.Date;@Slf4jpublicclassDateTimeUtil{publicstaticfinalStringDATE_PATTERN="yyyy-......
  • 如何避免Mysql的timestamp的大坑
    如何避免Mysql的timestamp的大坑Mysql的timestamp类型讨论需要测试MYSQL的同学,可以点以下链接免费试用腾讯云mysql服务器https://curl.qcloud.com/tgnMO3KJ一.时间戳字段定义timestamp时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起到......
  • 我应该在MySQL中使用datetime还是timestamp数据类型?
    内容来自DOChttps://q.houxu6.top/?s=我应该在MySQL中使用datetime还是timestamp数据类型?你推荐使用datetime还是timestamp字段,为什么(使用MySQL)?我正在服务器端使用PHP。在MySQL中,时间戳通常用于跟踪记录的更改,并且每次更改记录时通常都会更新。如果您想存储特定值,则应使用......
  • mysql 日期格式为timestamp 和 datetime 使用month 函数取月份的区别
    1.DATE_FORMAT(data_dt,'%m')as`month`,使用这种方式无论什么类型的时间,取到的都是两位数。2.timstamp格式时间使用month()函数取出的月份只有一位。3.atetime格式时,month()函数获取到的就是两位数的月份。注意相关工具使用会不按预期执行,我的代码取到的月份为一位数,补没......
  • 【转载】How to solve the problem that getting timestamp from Mysql database is 8
    Thisarticleintroducestherelevantknowledgeof"howtosolvetheproblemofobtainingtimestampfromMysqldatabase8hoursearlierthanthenormaltime".Intheoperationprocessofactualcases,manypeoplewillencountersuchdifficulties.......
  • 关于Date、LocalDate、LocalDateTime、Timestamp等时间类型的区别?
    最近在代码的开发过程中发现,小组内对于实体类中的时间字段。有的用Date,有的用Timestamp,有的又用LocalDateTime,于是我就想整理一下这些时间类型有什么区别,是否可以统一?1、Date(不推荐)Date类型是Java8之前的时间处理类,存在一些问题比如说非线程安全问题。时区的处理比较麻烦等。Da......