题意:
给出一个只包含小写字母的串 s 和n 个串t,判断t[i]是否为串 s 的子序列;
如果是,输出"YES",反之,输出"NO";
坑点:
二分一直TLE可还行;
具体思路+细节看代码(有点累了,不想写了)
AC代码:
扫描二维码关注公众号,回复:
5965359 查看本文章
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 #include<cstring> 5 using namespace std; 6 #define mem(a,b) memset(a,b,sizeof(a)) 7 const int maxn=1e5+50; 8 9 int n; 10 char s[maxn]; 11 char ch[maxn]; 12 int res[30]; 13 vector<int >v[30]; 14 /** 15 字母a~z转化为0~25 16 v[i]:i对应的字母在s中出现的所有位置 17 例如s="aabaa" 18 v[0]:0,1,2,3 19 v[1]:2 20 */ 21 22 bool isSat() 23 { 24 mem(res,0); 25 int cur=-1; 26 int len=strlen(ch); 27 for(int i=0;i < len;++i) 28 { 29 int x=ch[i]-'a'; 30 //在s串中找x出现的位置 > cur 的第一个位置 31 //res[x]记录之前x到达的最远位置,没有这个数组,TLE到死 32 while(res[x] < v[x].size() && v[x][res[x]] <= cur) 33 res[x]++; 34 //没找到,返回false 35 if(res[x] == v[x].size()) 36 return false; 37 cur=v[x][res[x]];//更新cur 38 } 39 return true; 40 } 41 void Solve() 42 { 43 int len=strlen(s); 44 for(int i=0;i < 30;++i) 45 v[i].clear(); 46 for(int i=0;i < len;++i) 47 v[s[i]-'a'].push_back(i); 48 49 for(int i=1;i <= n;++i) 50 { 51 scanf("%s",ch); 52 if(isSat())//判断串ch是否为串s的子序列 53 printf("YES\n"); 54 else 55 printf("NO\n"); 56 } 57 } 58 int main() 59 { 60 while(~scanf("%s",s)) 61 { 62 scanf("%d",&n); 63 Solve(); 64 } 65 return 0; 66 }
将32,33行的whlie()代码改成二分查找后,反而慢了,真是搞不懂哟,莫非,出题放的数据就是在卡二分???
更改后的isSat()函数:
1 int BS(int l,int r,int x,int val) 2 { 3 while(r-l > 1) 4 { 5 int mid=(l+r)/2; 6 if(v[x][mid] >= val) 7 r=mid; 8 else 9 l=mid; 10 } 11 return r; 12 } 13 bool isSat() 14 { 15 mem(res,-1); 16 int cur=-1; 17 int len=strlen(ch); 18 for(int i=0;i < len;++i) 19 { 20 int x=ch[i]-'a'; 21 res[x]=BS(res[x],v[x].size(),x,cur+1); 22 if(res[x] == v[x].size()) 23 return false; 24 cur=v[x][res[x]]; 25 } 26 return true; 27 }
while()遍历:
二分查找:
慢了将近一秒是什么鬼,阔怕~~~~~~~~~~
同样的二分代码晚上提交超时又是什么鬼,增加数据了???
《论评测机的性能与时间的关系??》