P1942 词编码_NOI导刊2011提高(10)
C++党的福音系列
其实这道题的题意有点乱。我在这里总结一下题意。
一个未知的01串,通过一次某种的变换,能够变成转换后的单词(输入的单词)。你的任务是倒推出转换前的单词。
可能有多解,但是正向转换的时候有考虑顺序:操作4(不改变)最优先,否则按操作1、2、3顺序为优先级。
操作2的时候先尝试删0,都不行再尝试删1。
那么我们的任务就是倒推出题意咯!
因为只有一次的变换,如果长度长于起始长度的话,一定是用了操作3,同理可以得到长度小于起始长度的情况。
我们可以使用std::string
里面的两个函数很暴力地解决这个问题:
-
std::string::insert(开始添加的下标,添加的字符串)
-
std::string::erase(开始删除的下标,删除的长度)
然后用暴力的方法去判断一个长度满足的字符串满不满足。
但是只能够得到80pts,剩下两个点T了。
显然,劣势在于进行了太多的暴力判断。
我们使用一个技巧:后缀和。
我们维护\([i,len-1]\)这段区间的原单词有多少个1,那么删除或者添加就可以直接通过\(O(1)\)的判断就可以搞出来了。
详见代码吧,很容易看懂的。
错误思路:处理后缀和的时候,面对多组数据却忘记清空!导致直接WA!一定要小心!
代码:
#include<iostream>
#include<string>
#include<queue>
#include<cstring>
using namespace std;
const int maxn = 1005;
int suf[maxn];
int n;
bool check(string x)
{
int res = 0, len = x.length();
for(int i = 0; i < len; i++) if(x[i] == '1') res += i + 1;
return res % (n + 1) == 0;
}
void solve(string word)
{
int len = word.length();
int res = 0;
for(int i = 0; i < len; i++) if(word[i] == '1') res += i + 1;
if(len == n)
{
if(res % (n + 1) == 0)
{
cout << word << endl;
return;
}
for(int i = 0; i < len; i++)
{
if(word[i] == '1' && (res - (i + 1)) % (n + 1) == 0)
{
word[i] = '0';
cout << word << endl;
return;
}
}
cout << -1 << endl;
}
else if(len < n)
{
for(int i = len - 1; i >= 0; i--) suf[i] = suf[i + 1] + (word[i] == '1');
string temp;
for(int i = 0; i <= len; i++)
{
temp = word;
temp.insert(i, "0");
//cout << temp << endl;
if((res + suf[i]) % (n + 1) == 0)
{
cout << temp << endl;
return;
}
}
for(int i = 0; i <= len; i++)
{
temp = word;
temp.insert(i, "1");
//cout << temp << endl;
if((res + suf[i] + i + 1) % (n + 1) == 0)
{
cout << temp << endl;
return;
}
}
cout << -1 << endl;
}
else if(len > n)
{
for(int i = len - 1; i >= 0; i--) suf[i] = suf[i + 1] + (word[i] == '1');
string temp;
for(int i = 0; i < len; i++)
{
temp = word;
temp.erase(i, 1);
if(word[i] == '1' && (res - suf[i + 1] - (i + 1)) % (n + 1) == 0)
{
cout << temp << endl;
return;
}
if(word[i] == '0' && (res - suf[i + 1]) % (n + 1) == 0)
{
cout << temp << endl;
return;
}
}
cout << -1 << endl;
}
}
int main()
{
ios::sync_with_stdio(false);
cin >> n;
string word;
while(cin >> word)
{
memset(suf, 0, sizeof suf);
solve(word);
}
return 0;
}