原地址 http://codeforces.com/problemset/problem/778/A
题意 有两个字符串t和p,t的长度为L,数组a里面有L个数,以数组A里面的数为标准 按顺序删去t中对应位置的字符,问最多删去几个字符,能够让p依旧是t的子串。
分析 每次删去字符后,我们都需要对比t和p,检测p是否依旧是t的子串。 但是这样需要检测的次数,将会很多,所以考虑使用二分的方法 减少检测的次数。
代码
#include<cstdio> #include <iostream> #include <cstring> using namespace std; const int N=200100; int a[N]; int vis[N]; char b[N]; char c[N]; int t,f,m,l,r,ans,L,n; int check(int m) //检测是否是其子串 { int start=0; for(int i=0;i<t;i++) vis[i]=0; for(int i=0;i<m;i++) vis[a[i]]=1; for(int i=0;i<t;i++) { if(!vis[i]) { // cout<<b[i]<<" "<<c[start]<<endl; if(b[i]==c[start]) start++; } } // cout<<"start="<<start<<endl; if(start==L) { return 1; } else return 0; } int main() { while(scanf("%s",b)!=EOF) { f=1; int num=0; scanf("%s",c); t=strlen(b); L=strlen(c); for(int i=0;i<t;i++) { cin>>a[i]; a[i]=a[i]-1; //字符串的长度从0开始,进行一个长度对应 } l=0,r=t-1;//最左端为1个都不能删的情况,最右边是只留下一个字符的情况。 while(l<=r) //l和r交叉后 m去到所有可能的值 { m=(l+r)/2; if(check(m)) { num=max(num,m); l=m+1; } else { r=m-1; } } cout<<num<<endl; } return 0; }