一.题目描述
基德发现了一个可能藏有宝藏的箱子。然而,箱子是锁着的。为了打开它,基德需要输入一个由小写英文字母组成的密码S。 基德在箱子边上发现了一张纸条,经过判断,发现这张纸条上记录了密码S',但是的一些字母因为年代原因模糊不清了,此处用'?'替换。 经过思考,基德找到了解密的方法: 1.密码S包含了一个连续的子串T 2.在满足1的所有字符串中,S是字典序最小的字符串。 如果存在这样的密码,输出S。否则输出UNRESTORABLE 输入 第一行一个字符串S'(长度不超过100),表示基德拿到的已经模糊不清的密码。 第二行一个字符串T(长度不超过100),表示密码S中的一个连续的子串。 输出 如果存在这样的密码,输出S。否则输出UNRESTORABLE 样例输入 Copy 【样例1】 ?cmc???? coder 【样例2】 ??p??d?? abc 样例输出 Copy 【样例1】 acmcoder 【样例2】 UNRESTORABLE
首先,先给各位介绍一个字符串的函数(只要是学过的人都应该懂啊),就是s.substr(i,L)。给不知道的读者简单介绍一下:substr()的功能是截取子串,比如说现在有一个字符串s为
kidfover
那么s.substr(0,3)就是“kid”;substr()的用法如上所见是:substr(下标i,长度L),这样一来就可以截取从下标i开始长度为L的s的子串了。另外也是需要注意的是,当i + L >= s.size()时,substr就会在最后结尾,按照上面的例子来说就可以是:
s.substr(5,8) = ver
有了上面的基础,这道题就变得很简单了。先上代码:
二.代码
#include<bits/stdc++.h>
#define MX 200000
using namespace std;
int main()
{
string s,t;
int i,j;
cin >> s >> t;
int len = s.size(),lent = t.size(),f = 0;
for (i = len - 1;i >= 0;i--)
{
string st = s.substr(i,lent);
if (st == t)
{
int k2 = i,c2 = i + lent - 1;
for (j = 0;j < k2;j++)
{
if (s[j] == '?')
{
cout << "a";
}
else
{
cout << s[j];
}
}
cout << t;
for (j = c2 + 1;j < len;j++)
{
if (s[j] == '?')
{
cout << "a";
}
else
{
cout << s[j];
}
}
f = 1;
break;
}
}
if (f == 0)
{
for (i = len - 1;i >= 0;i--)
{
string st = s.substr(i,lent);
int p = 0;
for (j = 0;j < st.size();j++)
{
if (st[j] == t[j] || st[j] == '?')
{
p++;
}
}
if (p == st.size() && st.size() == lent)
{
int k2 = i,c2 = i + lent - 1,p = -1;
for (j = 0;j < k2;j++)
{
if (s[j] == '?')
{
cout << "a";
}
else
{
cout << s[j];
}
}
cout << t;
for (j = c2 + 1;j < len;j++)
{
if (s[j] == '?')
{
cout << "a";
}
else
{
cout << s[j];
}
}
f = 1;
break;
}
}
}
if (f == 0)
{
cout << "UNRESTORABLE" << endl;
}
return 0;
}
三.程序部分
按照我的方法,就是要将整个程序分为三部分:第一部分是第10行-第42行,这一部分是来判断在不需要用到"?"的情况下,就可以找到一个字典序最小的字符串。比如说当s = kidtheik?? t = kid时,就不需要用到数据中的"?"了。为什么呢?因为虽然这个字符串可以变成kidtheikid(也就是将两个?变成id),但是字典序没有kidtheikaa大。也就是说,能不用“?”就不用,因为用了就会使字典序变大。
第二部分是43行-86行,这一部分是用来判断当需要用到“?”的情况下,找到一个字典序最小的字符串。比如说样例一。
第三部分是剩下的代码,这一部分是用来判断无法找到字符串的情况。比如样例二。
四.解题思路
贯通于第一,第二部分的思路就是利用刚刚给大家介绍的函数s.substr()来做题。
首先,让字符串st = s.substr(i,lent),也就是从s的下标i,长度为lent的子串;然后再利用第二层循环遍历st,看看st和字符串t是否一致,注意,当st[j] = '?'时,就可以不用管,也就是权当它与t[j]相同。如果st的一个字符都与t相同(?除外),就输出st。
最后的输出也要有技巧(我的输出只是一种,某些大神有比我更好的解法),当j是在st在s的初始端点的左边时(j < k2)遇到“?”就输出a(因为要保证字典序最小),如果不是“?”直接输出s[j],在(j >= k2 && j <= c2)时,直接输出t;在(j > c2)时,与在(j < k2)时一样。
此外还要有一个变量f充当“线索”贯穿整个程序,在f最后仍然等于0时,就说明没有结果(st),就输出“UNRESTORABLE”。
五.注意事项
字符串st表示的是字符串s中的一个子串(可能有“?”)t可以看成是st中除了“?”都与st相同的字符串(无“?”);这两点要区分好,否则就会想我一样没搞好关系,第一次错了85%。
六.
-加上这个才算完美-