[CodeForces-332E]Binary Key

题目大意:
  给你两个字符串p和s,让你求出一个字典序尽量小的长度为k的01串密钥,能将p转化为s。
  密钥的工作方式如下:
  第i位是0,表示这一位无用;
  第i位是1,表示这一位有用。
  若密钥的长度比s短,则可以通过循环的方式补齐。

思路:
  由于密钥的长度为固定的k,我们可以先预处理出k个字符串p1,其中p1[i]是p中所有位置在mod k意义下为i的字符所构成的串。
  接下来我们枚举密钥中出现的1的个数,对应的是密钥循环的周期长度。
  每次还要处理出字符串s对应的s1。
  然后从后往前贪心,枚举p1中的每个字符串p1[i]和s1中的每个字符串s1[p],如果p1[i]==s1[p]那么这一位可以是1。
  由于是从后往前贪心,在这里选1肯定是相对更优的。
  然后对于不同的1的个数,我们都可以找出一个字典序最小的密钥tmp,最后再找出其中字典序最小的即可。
  注意字符串中可能会有空格和一堆奇怪的字符,所以必须得getline。

 1 #include<string>
 2 #include<iostream>
 3 #include<algorithm>
 4 const int K=2001;
 5 int k,p_len,s_len;
 6 std::string p,s,p1[K],s1[K],ans;
 7 int main() {
 8     std::ios_base::sync_with_stdio(false);
 9     std::cin.tie(NULL);
10     std::getline(std::cin,p);
11     std::getline(std::cin,s);
12     std::cin>>k;
13     p_len=p.length(),s_len=s.length();
14     for(register int i=0;i<p_len;i++) {
15         p1[i%k]+=p[i];
16     }
17     ans="2";
18     int max_period=std::min(k,s_len);
19     for(register int i=1;i<=max_period;i++) {
20         for(register int j=0;j<i;j++) {
21             s1[j]="";
22         }
23         for(register int j=0;j<s_len;j++) {
24             s1[j%i]+=s[j];
25         }
26         std::string tmp;
27         int p=i-1;
28         for(register int i=k-1;i>=0;i--) {
29             if(p>=0&&p1[i]==s1[p]) {
30                 p--;
31                 tmp+="1";
32             } else {
33                 tmp+="0";
34             }
35         }
36         if(p<0) {
37             std::reverse(tmp.begin(),tmp.end());
38             ans=std::min(ans,tmp);
39         }
40     }
41     if(ans=="2") ans="0";
42     std::cout<<ans<<std::endl;
43     return 0;
44 }

 

posted @ 2017-10-10 15:23  skylee03  阅读(211)  评论(0编辑  收藏  举报