TOPCODER->Practice Room->SRAM 144 DIV 1 (300)
问题描述
若你有一个二进制字符串如下:
011100011
其中一个加密这些字符串的方法是将各个数字与其相邻的数字相加。例如,加密后字符串会是这样:
123210122
若p是原本的字符串,Q是加密的字符串,那么Q[i] = P[i-1] + P[i] + P[i+1],i是数字的位置。超过字符串左边界和右边界的字符作0处理。
以这种格式给你的加密字符串可以以如下方式解密(以123210122为例):
1. 假设 P[0] = 0.
2. 因为 Q[0] = P[0] + P[1] = 0 + P[1] = 1, 我们得到 P[1] = 1.
3. 因为 Q[1] = P[0] + P[1] + P[2] = 0 + 1 + P[2] = 2, 我们得到 P[2] = 1.
4. 因为 Q[2] = P[1] + P[2] + P[3] = 1 + 1 + P[3] = 3, 我们得到 P[3] = 1.
5. 重复以上步骤得到 P[4] = 0, P[5] = 0, P[6] = 0, P[7] = 1, 以及 P[8] = 1.
6. 检查我们的工作并注意 Q[8] = P[7] + P[8] = 1 + 1 = 2. 若这个等式成立,那么我们就得到了一个可能的原字符串。
现在我们重复以上步骤,并假设P[0]为相反的值
1. 假设P[0]=1.
2. 因为 Q[0] = P[0] + P[1] = 1 + P[1] = 0, 我们得到 P[1] = 0.
3. 因为 Q[1] = P[0] + P[1] + P[2] = 1 + 0 + P[2] = 2, 我们得到 P[2] = 1.
4. 现在注意 Q[2] = P[1] + P[2] + P[3] = 0 + 1 + P[3] = 3, 可知道 P[3] = 2.然而,这违反了原字符串里的字符必须为0或1的事实。因此,第一个字符为1的原字符串是不存在的。
注意,对于任意给出的加密字符串,这个算法至多需要两次解密。若字符串的第一个二进制数已确定,那么就只有一种方法来解析。给你一个包含了加密字符串的字符串信息,需要返回一个包含了两个元素的string[]。第一个元素需要包含第一个字符为0的解密后字符串;第二个元素需要包含第一个字符为1的解密后字符串。如果其中某个尝试失败了,就在该位置上返回"NONE"字符串。对于上面的例子,你需要返回{"011100011","NONE"}。
定义
Class: BinaryCode
Method: decode
Parameters: string
Returns: string[]
Method signature: string[] decode(string message)
(确保你的method是public的)
约束
- 字符串信息将包含1到50个字符
- 字符串信息中的字符将会是'0','1','2','3'中的其中一个
例子
0)
"123210122"
Returns: { "011100011", "NONE" }
上面的实例
1)
"11"
Returns: { "01", "10" }
其中一个数字必须是'1,另一个必须是'0'。两种情况我们都返回
2)
"22111"
Returns: { "NONE", "11001" }
若加密字符串的第一个字符为'2',那么其原字符的前两个数字必须为'1'。若我们假设P[0]=0,这个尝试就会失败。
3)
"123210120"
Returns: { "NONE", "NONE" }
这跟1号实例一样,不过考虑原字符串的话,最右边的数字不可能出现。没有解决方案。
4)
"3"
Returns: { "NONE", "NONE" }
5)
"12221112222221112221111111112221111"
Returns: "01101001101101001101001001001101001","10110010110110010110010010010110010" }
This problem statement is the exclusive and proprietary property of TopCoder, Inc. Any unauthorized use or reproduction of this information without the prior written consent of TopCoder, Inc. is strictly prohibited. (c)2003, TopCoder, Inc. All rights reserved
解析:
已知一加密字符串Q和两原字符串P0和P1,其中P0的第一个字符为'0',P1的第一个字符为'1'
又,我们知道Q[i]=P[i-1]+P[i]+P[i+1]
其中:1)Q[i]已知 2)i=0时,P[i-1]、P[i]已知
所以i=0时:P[i+1]=Q[i]-P[i-1]-P[i]
故可得,当i=1时的P[i-1]、P[i]
依次类推,可得P0和P1字符串
解答:
(以P0为例)
1 使用for循环遍历字符串Q
class BinaryCode { public string[] decode(string message) { string Q = message; //遍历Q for (int i = 0; i < Q.Length-1; i++) { } } }
2 在for循环中求解P[i+1]
class BinaryCode { public string[] decode(string message) { string Q = message; string PiA1 = "0";//P[i+1] string Pi = "0";//P[i] string PiS1 = "0";//P[i-1] //遍历Q for (int i = 0; i < Q.Length-1; i++) { //计算P[i+1] PiA1 = (int.Parse(Q[i].ToString()) - int.Parse(PiS1) - int.Parse(Pi)).ToString();//P[i+1] = Q[i] - P[i-1] - P[i] PiS1 = Pi;//next P[i-1] = P[i] Pi = PiA1;//next P[i] = P[i+1] } } }
3 将计算结果累积到P0字符串
class BinaryCode { public string[] decode(string message) { string P0 = "";//P0字符串 string Q = message; string PiA1 = "0";//P[i+1] string Pi = "0";//P[i] string PiS1 = "0";//P[i-1] P0 = P0 + Pi; //遍历Q for (int i = 0; i < Q.Length-1; i++) { //计算P[i+1] PiA1 = (int.Parse(Q[i].ToString()) - int.Parse(PiS1) - int.Parse(Pi)).ToString();//P[i+1] = Q[i] - P[i-1] - P[i] PiS1 = Pi;//P[i-1] = P[i] Pi = PiA1;//P[i] = P[i+1] //将结果累积到P0 P0 = P0 + Pi; } } }
4 添加边界条件
边界条件1:i=0时 P[i]=0 P[i-1]=0
边界条件2:i=Q.Length-2时 P0已计算完毕,但Q的最后一位仍需验证,其中P[i+1]=0
边界条件3:若Q只有一位,仅验证Q是否正确,其中P[i+1]=0 P[i-1]=0 P[I]已知
class BinaryCode { public string[] decode(string message) { string[] result = new string[2];//结果 string P0 = "";//P0字符串 string Q = message; string PiA1 = "0";//P[i+1] string Pi = "0";//P[i] string PiS1 = "0";//P[i-1] P0 = P0 + Pi; //边界条件3:Q只有一位 仅验证P是否正确,其中P[i+1]=0 P[i-1]=0 if (Q.Length == 1) { PiA1 = "0"; PiS1 = "0"; Pi = P0; if (int.Parse(Q.ToString()) != int.Parse(PiS1) + int.Parse(Pi) + int.Parse(PiA1))//Q[i]!=P[i-1]+P[i]+P[i+1] { result[0] = "NONE";; } else { result[0] = P0; } } //遍历Q for (int i = 0; i < Q.Length - 1; i++) { //边界条件1:i=0时 P[i]=0 P[i-1]=0 if (i == 0) { PiS1 = "0"; Pi = "0"; } //计算P[i+1] PiA1 = (int.Parse(Q[i].ToString()) - int.Parse(PiS1) - int.Parse(Pi)).ToString();//P[i+1] = Q[i] - P[i-1] - P[i] PiS1 = Pi;//next P[i-1] = P[i] Pi = PiA1;//next P[i] = P[i+1] //将结果累积到P0 P0 = P0 + Pi; //边界条件2:i=Q.Length-2时 P0已计算完毕,但Q的最后一位仍需验证,其中P[i+1]=0 if (i == Q.Length - 2) { PiA1 = "0";//P[i+1]=0 if (int.Parse(Q[i + 1].ToString()) != int.Parse(PiS1) + int.Parse(Pi) + int.Parse(PiA1))//Q[i+1]!=P[i-1]+P[i]+P[i+1] { result[0] = "NONE";//算了半天答案是错的 } else { result[0] = P0;//算对了 } } } } }
5 添加校验条件
class BinaryCode { public string[] decode(string message) { string[] result = new string[2];//结果 string P0 = "";//P0字符串 string Q = message; string PiA1 = "0";//P[i+1] string Pi = "0";//P[i] string PiS1 = "0";//P[i-1] P0 = P0 + Pi; //边界条件3:Q只有一位 仅验证P是否正确,其中P[i+1]=0 P[i-1]=0 if (Q.Length == 1) { PiA1 = "0"; PiS1 = "0"; Pi = P0; if (int.Parse(Q.ToString()) != int.Parse(PiS1) + int.Parse(Pi) + int.Parse(PiA1))//Q[i]!=P[i-1]+P[i]+P[i+1] { result[0] = "NONE"; ; } else { result[0] = P0; } } //遍历Q for (int i = 0; i < Q.Length - 1; i++) { //边界条件1:i=0时 P[i]=0 P[i-1]=0 if (i == 0) { PiS1 = "0"; Pi = "0"; } //计算P[i+1] PiA1 = (int.Parse(Q[i].ToString()) - int.Parse(PiS1) - int.Parse(Pi)).ToString();//P[i+1] = Q[i] - P[i-1] - P[i] //校验条件 if (PiA1 != "0" && PiA1 != "1" && PiA1 != "2" && PiA1 != "3")//字符串信息中的字符将会是'0','1','2','3'中的其中一个 { result[0] = "NONE"; break;//退出计算 } PiS1 = Pi;//next P[i-1] = P[i] Pi = PiA1;//next P[i] = P[i+1] //将结果累积到P0 P0 = P0 + Pi; //边界条件2:i=Q.Length-2时 P0已计算完毕,但Q的最后一位仍需验证,其中P[i+1]=0 if (i == Q.Length - 2) { PiA1 = "0";//P[i+1]=0 if (int.Parse(Q[i + 1].ToString()) != int.Parse(PiS1) + int.Parse(Pi) + int.Parse(PiA1))//Q[i]!=P[i-1]+P[i]+P[i+1] { result[0] = "NONE";//算了半天答案是错的 } else { result[0] = P0;//算对了 } } } return result; } }
6 测试
private void button1_Click(object sender, EventArgs e) { string[] result = new string[2]; BinaryCode binaryCode = new BinaryCode(); result = binaryCode.decode("12221112222221112221111111112221111"); MessageBox.Show(result[0]); }
7 考虑P1的情况,进行整合
class BinaryCode { private string getcode(string head,string Q) { string PiA1 = "";//P[i+1] string Pi = "";//P[i] string PiS1 = "";//P[i-1] string P = "";//P字符串 P = P + head; //边界条件3:Q只有一位 仅验证P是否正确,其中P[i+1]=0 P[i-1]=0 if (Q.Length == 1) { PiA1 = "0"; PiS1 = "0"; Pi = P; if (int.Parse(Q.ToString()) != int.Parse(PiS1) + int.Parse(Pi) + int.Parse(PiA1))//Q[i]!=P[i-1]+P[i]+P[i+1] { return "NONE"; } else { return P; } } for (int i = 0; i < Q.Length - 1; i++) { //边界条件1:i=0时 P[i]=P[0] P[i-1]=0 if (i == 0) { PiS1 = "0"; Pi = P; } //计算P[i+1] PiA1 = (int.Parse(Q[i].ToString()) - int.Parse(PiS1) - int.Parse(Pi)).ToString();//P[i+1] = Q[i] - P[i-1] - P[i] //校验条件 if (PiA1 != "0" && PiA1 != "1" && PiA1 != "2" && PiA1 != "3")//字符串信息中的字符将会是'0','1','2','3'中的其中一个 { return "NONE"; } PiS1 = Pi;//next P[i-1] = P[i] Pi = PiA1;//next P[i] = P[i+1] //将结果累积到P P = P + Pi; //边界条件2:i=Q.Length-2时 P0已计算完毕,但Q的最后一位仍需验证,其中P[i+1]=0 if (i == Q.Length - 2) { PiA1 = "0";//P[i+1]=0 if (int.Parse(Q[i + 1].ToString()) != int.Parse(PiS1) + int.Parse(Pi) + int.Parse(PiA1))//Q[i]!=P[i-1]+P[i]+P[i+1] { return "NONE";//算了半天答案是错的 } else { return P;//算对了 } } } return P; } public string[] decode(string message) { string[] result = new string[2];//结果 result[0] = getcode("0", message); result[1] = getcode("1", message); return result; } }
8 测试
private void button1_Click(object sender, EventArgs e) { string[] result = new string[2]; BinaryCode binaryCode = new BinaryCode(); result = binaryCode.decode("123210122"); MessageBox.Show(result[0]+"\n"+result[1]); }