Educational Codeforces Round 81 (Rated for Div. 2) C. Obtain The String

题目链接:http://codeforces.com/contest/1295/problem/C

题目:给定字符串s,t.  给定一个空串z,需要按照规则把z构造成

string z == string t 的字符串。

规则:有限次从s中任取子序列p,然后进行 string z += string p的操作,

s不变。

问能不能构造出p,不能输出-1,可以得话最少几次可以构造出。

大致的想法就是n倍的s字符串串联,然后剔除不必要的字符,就可以得出z,

求最少的倍数n是多少。

主要思路就是用二分去减少时间复杂度,应该是n = 1e5,

<O(n*log(n))。特判-1很简单。然后把s中'a'~'z'存在的字符下标都统计出来,

然后有一个flag表示当前位于s的哪一个位置,我们要充分利用s,所以二分出当前字符最接近flag的位置,

当然要>flag,如果找到了,那就更新flag的位置。如果找不到位置了,说明当前的s已经无用了,需要从新的s中找,

那么ans就要加1,flag就是第一个当前字符出现的位置,然后继续。

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <string>
  4 #include <cstring>
  5 #include <cstdio>
  6 #include <vector>
  7 using namespace std;
  8  
  9 const int INF = (int)1e9;
 10  
 11 struct info{
 12     vector<int> loc[30];
 13     string s;
 14     int cnt,flag;
 15     void init(){
 16         for(int i = 0; i < 26; ++i) loc[i].clear();
 17         cnt = 1; flag = -1;
 18     }
 19     //统计'a'~'z'的下标
 20     void count(){
 21         int index,l = s.length();
 22         for(int i = 0; i < l; ++i){
 23             index = s[i]-'a';
 24             loc[index].push_back(i);
 25         }
 26     }
 27     //特判
 28     bool error(string& x){
 29         int index,l = x.length();
 30         for(int i = 0; i < l; ++i){
 31             index = x[i]-'a';
 32             if(loc[index].size()) continue;
 33             return true;
 34         }
 35         return false;
 36     }
 37     void show(){
 38  
 39         for(int i = 0; i < 26; ++i){
 40             if(!loc[i].size()) continue;
 41             cout << char('a'+i) << endl;
 42             for(int j = 0; j < loc[i].size(); ++j){
 43                 cout << loc[i][j] << ' ';
 44             }cout << endl;
 45         }
 46     }
 47     void work(string& x){
 48  
 49         int index,l,r,mid,now;
 50         int len = x.length();
 51  
 52  
 53         for(int i = 0; i < len; ++i){
 54             index = x[i]-'a';
 55             l = 0; r = loc[index].size()-1;
 56             now = INF;
 57             //二分找答案
 58             while(l <= r){
 59                 mid = (l+r) >> 1;
 60                 if(loc[index][mid] > flag){
 61                     now = loc[index][mid];
 62                     r = mid - 1;
 63                 }else l = mid + 1;
 64             }
 65             //找到答案,更新flag
 66             if(now != INF) flag = now;
 67             else{//没找到答案,答案加一
 68                  //flag为下一个s的该字符出现的第一个位置
 69                 flag = loc[index][0];
 70                 ++cnt;
 71             }
 72         }
 73     }
 74 }S;
 75  
 76 int main(){
 77  
 78     int T;
 79     cin >> T;
 80     while(T--){
 81         string t;
 82         cin >> S.s >> t;
 83         S.init();
 84         S.count();
 85         //S.show();
 86         if(S.error(t)){
 87             cout << -1 << endl;
 88         }else{
 89             S.work(t);
 90             cout << S.cnt << endl;
 91         }
 92     }
 93 }
 94 
 95 /*
 96 99
 97 aabce
 98 ace
 99 abacaba
100 aax
101 ty
102 yyt
103 aceaceace
104 aceaceaceace
105 aceaceace
106 acceae
107 
108 */

猜你喜欢

转载自www.cnblogs.com/SSummerZzz/p/12246920.html