给出字符串s和t,以及s的长度n的一个全排列,求按照这个排列依次删除s的字符,删到何时s中不含子序列t。

解法一:

t中的每个字符的位置在s中跳啊跳,合法的情况下t中的字符在s中的位置应该是单调递增的,因此让t中的字符在s中建的邻接表里跳啊跳就好了。

 #include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std; #define maxs 200011
char s[maxs];int ls;
char t[maxs];int lt;
int first[],next[maxs],P[maxs];
bool vis[maxs];
bool Play(int x)
{
if (x==lt-) return ;
if (P[x+]<=P[x])
{
while (P[x+]!=- && (P[x+]<=P[x] || vis[P[x+]])) P[x+]=next[P[x+]];
if (P[x+]==-) return ;
return Play(x+);
}
return ;
}
int x;
int find(int x)
{
int L=,R=lt-;
while (L<R)
{
int mid=(L+R)>>;
if (x<=P[mid]) R=mid;
else L=mid+;
}
return L;
}
int main()
{
scanf("%s",s);ls=strlen(s);
scanf("%s",t);lt=strlen(t);
memset(first,-,sizeof(first));
for (int i=ls-;i!=-;i--)
{
int now=s[i]-'a'+;
next[i]=first[now];
first[now]=i;
}
int ans=;
for (int i=;i<lt;i++)
P[i]=first[t[i]-'a'+];
bool flag=;
for (int i=;i<lt-;i++)
if (!Play(i)) {flag=;break;}
if (flag)
{
memset(vis,,sizeof(vis));
for (int i=;i<ls;i++)
{
scanf("%d",&x);x--;
vis[x]=;
int pos=find(x);
if (P[pos]==x)
{
P[pos]=next[P[pos]];
while (P[pos]!=- && vis[P[pos]]) P[pos]=next[P[pos]];
if (P[pos]==-) break;
if (!Play(pos)) break;
}
ans++;
// for (int j=0;j<ls;j++) cout<<vis[j]<<' ';cout<<endl;
// for (int j=0;j<lt;j++) cout<<P[j]<<' ';cout<<endl;
}
}
printf("%d\n",ans);
return ;
}

该代码在随机数据下表现良好,因此如果是oi赛制可以拿到不错的分数。但是理论复杂度是n2的,而且存在aaaa……这样的数据使得t中每个字符都要跳n次。

解法二:

我们要在排列中找一个位置,它左边的都符合某个条件,而右边都不符合。二分!!

 #include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cmath>
//#include<iostream>
using namespace std; #define maxs 200011
char s[maxs];int ls;
char t[maxs];int lt;
int a[maxs];
bool vis[maxs];
int main()
{
scanf("%s%s",s,t);
ls=strlen(s),lt=strlen(t);
for (int i=;i<ls;i++) scanf("%d",&a[i]),a[i]--;
int L=,R=ls-;
while (L<R)
{
int mid=(L+R+)>>;
memset(vis,,sizeof(vis));
for (int i=;i<mid;i++) vis[a[i]]=;
int j=;
for (int i=;i<ls;i++)
if (j<lt && s[i]==t[j] && !vis[i]) j++;
if (j==lt) L=mid;
else R=mid-;
}
printf("%d\n",L);
return ;
}

最新文章

  1. Oracle段收缩功能
  2. MySQL命令行登录的例子
  3. zigbee学习之路(十三):基于协议栈的Usart 实验
  4. sql server 更新视图的sp
  5. 求最大公约数和小于n的所有质数
  6. iOS9支付完成无法获取回调
  7. 关于List.ToArray()方法的效率测试
  8. SSIS -&gt;&gt; Error Handling
  9. oc-04-类的声明和实现
  10. 为什么a标签中使用img后的高度多了几个像素?
  11. HDU 2647
  12. 【转】 ubuntu12.04更新源 官网和163等
  13. 2014第8周三杂记及web标准学习
  14. 基于嵌入式OS的任务设计-----任务划分
  15. 利用PHPCMS V9站群功能建立分站
  16. 版本控制之四:SVN客户端重新设置帐号和密码(转)
  17. IOS 看懂此文,你的block再也不需要WeakSelf弱引用了!
  18. PC端问题列表及解决方案
  19. Rk3288 双屏异显单触摸
  20. Java多线程:AQS

热门文章

  1. 2019/05/11 JAVA虚拟机原理堆、栈、方法区概念区别
  2. Android Platform Version 和 API Level对照
  3. 正确使用MySQL JDBC setFetchSize()方法解决JDBC处理大结果集 java.lang.OutOfMemoryError: Java heap space
  4. sqlserver2012 offset
  5. webpack3整理(第三节/满三节)------(base.config文件解释)
  6. uva1412 Fund Management
  7. ansible2.7学习笔记系列
  8. Linux的Network Tunnel技术
  9. xcode菜单栏
  10. 洛谷——P3801 红色的幻想乡