博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2016集训测试赛(二十四)Problem B: Prz
阅读量:5245 次
发布时间:2019-06-14

本文共 2371 字,大约阅读时间需要 7 分钟。

Description

Solution

这道题有两个关键点:

  • 如何找到以原串某一个位置为结尾的某个子序列的最晚出现位置
  • 如何找到原串中某个位置之前的所有数字的最晚出现位置中的最大值

第一个关键点: 我们注意到每个数字在\(M\)\(L\)中最多只会出现一次. 以\(M\)为例, 我们从前往后逐位在原串中匹配, 数组f[i]表示\(M\)的前\(i\)位在原串中当前位置之前的最晚出现位置. 假设当前数字\(x\)\(M\)中出现位置为\(p\), 则

\[ f[p] = \begin{cases} f[p] = i, \ p == 1 \\ f[p] = f[p - 1], \ p > 1 \end{cases} \]
至于其他长度的子序列, 其最晚出现位置并不会发生变化.

第二个关键点: 我们记录每个数字的最晚出现位置即可.

#include 
#include
#include
#include
using namespace std;namespace Zeonfai{ inline int getInt() { int a = 0, sgn = 1; char c; while(! isdigit(c = getchar())) if(c == '-') sgn *= -1; while(isdigit(c)) a = a * 10 + c - '0', c = getchar(); return a * sgn; }}const int N = (int)1e6, M = (int)1e6;int main(){#ifndef ONLINE_JUDGE freopen("prz.in", "r", stdin); freopen("prz.out", "w", stdout);#endif using namespace Zeonfai; int len = getInt(), m = getInt(); static int a[N + 1], s[N + 1], t[N + 1]; for(int i = 1; i <= len; ++ i) a[i] = getInt(); int lenS = getInt(), lenT = getInt(); for(int i = 1; i <= lenS; ++ i) s[i] = getInt(); for(int i = 1; i <= lenT; ++ i) t[i] = getInt(); static int mp[N + 1]; memset(mp, -1, sizeof(mp)); for(int i = 1; i <= lenS; ++ i) mp[s[i]] = i; static int rec[N + 1]; memset(rec, -1, sizeof(rec)); static int f[N + 1], g[N + 1]; for(int i = 1; i <= len; ++ i) { if(~ mp[a[i]]) { if(mp[a[i]] == 1) rec[mp[a[i]]] = i; else rec[mp[a[i]]] = rec[mp[a[i]] - 1]; } f[i] = rec[lenS]; } memset(mp, -1, sizeof(mp)); for(int i = 1; i <= lenT; ++ i) mp[t[i]] = i; memset(rec, -1, sizeof(rec)); for(int i = len; i; -- i) { if(~ mp[a[i]]) { if(mp[a[i]] == 1) rec[mp[a[i]]] = i; else rec[mp[a[i]]] = rec[mp[a[i]] - 1]; } g[i] = rec[lenT]; } memset(mp, -1, sizeof(mp)); for(int i = len; i; -- i) if(mp[a[i]] == -1) mp[a[i]] = i; static int lst[N + 1]; lst[0] = -1; for(int i = 1; i <= len; ++ i) lst[i] = max(mp[a[i]], lst[i - 1]); int cnt = 0; static int ans[N]; for(int i = 1; i <= len; ++ i) if(~ f[i] && ~ g[i] && a[i] == s[lenS] && lst[f[i] - 1] > g[i]) ans[cnt ++] = i; printf("%d\n", cnt); for(int i = 0; i < cnt; ++ i) printf("%d ", ans[i]);}

转载于:https://www.cnblogs.com/ZeonfaiHo/p/7519029.html

你可能感兴趣的文章
python之pymysql模块学习(待完善...)
查看>>
网站名记录
查看>>
简述下Objective-C中调用方法的过程(runtime)
查看>>
fork,vfork和clone底层实现
查看>>
给织梦添加英文栏目标题在chanel标签中调用
查看>>
电脑高手常用的五个按钮
查看>>
心得5--JSP标签和java bean详细介绍
查看>>
jquey ajax 将变量值封装json传入JAVA action获取解析
查看>>
Log4net_配置
查看>>
高精度正整数除法 大整数除法
查看>>
2016/9/9
查看>>
剑指offer 面试48题
查看>>
Python(四):数字连珠2
查看>>
GitLab 安装(推荐)
查看>>
预加载图片
查看>>
codevs1226 倒水问题
查看>>
SQL Server 2012使用OFFSET/FETCH NEXT分页及性能测试
查看>>
(线段树)敌兵布阵--hdu--1166 (入门)
查看>>
Javascript 对象的创建和属性的判定
查看>>
通过pycharm使用git
查看>>