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 <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm> 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]);
}

最新文章

  1. [PHP] - Laravel - 修改laravel_session的cookie名称
  2. Android 触摸事件处理机制
  3. 关于VS打开cshtml出现 未能完成该操作。无效指针
  4. Glossary of view transformations
  5. PHP5.4连接sqlserver
  6. Memory Cache(内存缓存)
  7. text与button上下不对齐解决方法
  8. Innodb_buffer_pool_pages_dirty [一个故事@MySQL DBA]MYSQL
  9. 关于Asp.Net中避免用户连续多次点击按钮,重复提交表单的处理
  10. 如何在Sqlserver2000查询分析器中,,在一个库中调用另一个数据库中的数据表
  11. Bozo排序
  12. PHP 底层的运行机制与原理 --转
  13. css3 box-shadow阴影(外阴影与外发光)讲解
  14. 解决C#中FileSystemWatcher类的Changed事件触发多次的问题
  15. leecode第二天-使用异或找出数组中的非重复元素
  16. Mac使用Clion配置OpenGL
  17. Hibernate(6)关联关系_单向n对1
  18. Win10系统的SurfacePro4如何重装系统-4 如何再次备份和还原系统
  19. 《linux就该这么学》第八节课:第六章存储结构与磁盘划分
  20. linux下安装haproxy作为端口转发服务器,以及安装keepalived作为haproxy高可用方案

热门文章

  1. Maya材质
  2. Flask With
  3. 分布式存储系统可靠性系列五:副本放置算法 &amp; CopySet Replication
  4. 设计模式之第13章-职责链模式(Java实现)
  5. 聊聊、Spring 数据源
  6. jqgrid postData setGridParam 调用多次时查询条件累加的问题
  7. php+mysqli预处理技术实现添加、修改及删除多条数据的方法
  8. Django模板中include的标签的使用
  9. ios 瀑布流的那些事情
  10. ofbiz数据库表结构设计(3)- 订单ORDER