P1942 詞編碼_NOI導刊2011提高(10)
阿新 • • 發佈:2018-11-06
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; }