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 */

原文地址:https://www.cnblogs.com/SSummerZzz/p/12246920.html

时间: 2024-08-30 14:43:35

Educational Codeforces Round 81 (Rated for Div. 2) C. Obtain The String的相关文章

Educational Codeforces Round 81 (Rated for Div. 2) B. Infinite Prefixes

题目链接:http://codeforces.com/contest/1295/problem/B 题目:给定由0,1组成的字符串s,长度为n,定义t = sssssss.....一个无限长的字符串. 题目定义一个平衡值x,取t的任意前缀Q,如果Q满足cnt(0,q) - cnt(1,q) = x,即Q中0 的个数-1的个数= x,说明当前的Q是满足题意得一个前缀,问满足x的前缀有多少个, 如果x = ∞,则输出-1. input 6 10 010010 题目给定说q的长度为28,30,32是平

【Educational Codeforces Round 81 (Rated for Div. 2) A】Display The Number

题目链接 [题解] 优先用2个棒子来凑1. 如果为奇数的话,多出来一根用3根来凑个7放在开头 [代码] #include <bits/stdc++.h> using namespace std; int main(){ #ifdef LOCAL_DEFINE freopen("E:\\rush.txt","r",stdin); #endif // LOCAL_DEFINE ios::sync_with_stdio(0),cin.tie(0); int T

Educational Codeforces Round 81 (Rated for Div. 2)

A - Display The Number 题意:给n根火柴,拼出最大的数字. 题解:肯定是数字越多越大,所以尽可能多拿最便宜的2根火柴一个"1",多余的肯定是拿一个"7",由于n>=2,没有特例. void test_case() { int n; scanf("%d", &n); if(n % 2 == 1) { printf("%d", 7); n -= 3; } while(n) { printf(&q

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

题目链接 [题解] 显然我们得按顺序获得目标t的每个字符. 对于t[0],t[1],t[2],t[3]... 我们可以在s中找到这么一个子序列. 显然如果找到尾巴还是没有需要的t[i]. 就得从s[0]开始重新开始顺序找. (然后答案递增,因为表示要重新开始加一个子序列了) 但是如果这么直接找的话,复杂度是O(|s||t|)的 是无法接受的. 所以我们可以另外开一个数组 next[i][j] 表示在i-1位置,如果要找下一个紧接着的j的话,需要到哪个位置找.(这个next数组整体往左偏移了下,便

【Educational Codeforces Round 81 (Rated for Div. 2) B】Infinite Prefixes

题目链接 [题解] 把0看成是1,把1看成是-1 求一个前缀和. pre[i] = pre[i-1]+1 得到delta = pre[n] 显然对于每个位置的值pre[i] 再复制一遍s的话. 下一个s的该位置,也即i+n的前缀和显然为pre[i]+delata 那么无限的情况就很显然了. 即pre[i]==x,而且delata==0. 只要出现一个这种情况,就是无限. 其他情况,每个位置都会朝着目标远离或者毕竟. 看看差值不是不是delta的整数倍就可以了. 如果是的话,说明可以变成x [代码

Educational Codeforces Round 81 (Rated for Div. 2) A Display The Number

A. Display The Number time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output You have a large electronic screen which can display up to 998244353998244353 decimal digits. The digits are displayed

Educational Codeforces Round 81 (Rated for Div. 2)F(线段树)

预处理把左集划分为大小为1~i-1时,把全部元素都移动到右集的代价,记作sum[i]. 然后枚举终态时左集的大小,更新把元素i 留在/移动到 左集的代价. 树状数组/线段树处理区间修改/区间查询 1 #define HAVE_STRUCT_TIMESPEC 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define ll long long 5 const int N=2e5+7; 6 struct Tree{ 7 ll minn,la

Educational Codeforces Round 77 (Rated for Div. 2) B. Obtain Two Zeroes

题目:https://codeforces.com/contest/1260/problem/B 思路:易得成立的条件为:\((a+b)\mod3==0\) && \(max(a,b)\le min(a,b)*2\) #include<bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0); int T;cin>>T; while(T--) {

Educational Codeforces Round 60 (Rated for Div. 2) E. Decypher the String

题目大意:这是一道交互题.给你一个长度为n的字符串,这个字符串是经过规则变换的,题目不告诉你变换规则,但是允许你提问3次:每次提问你给出一个长度为n的字符串,程序会返回按变换规则变换后的字符串,提问3次后你需要猜出这个字符串.解法是学习https://blog.csdn.net/baiyifeifei/article/details/87807822 这个博主的,借用了进制的思想非常巧妙. 解法:对于某个位置的来源位置我们设为x,因为26*26*26>10000,那么x可以唯一表示为x=a*26