C++ 中的序列蓋印
假設我們想要建立一個由小寫字母組成的目標字串。
首先,我們有一個序列,包含 n 個“?”標記(n 是目標字串的長度)。我們還有一個由小寫字母組成的印章。
在每一輪中,我們可以在序列上放置印章,並用印章中對應的字母替換序列中的每個字母。您可以最多進行 10 * n 輪。例如,如果初始序列為“?????”,印章為“abc”,那麼在第一輪中我們可以建立諸如“abc??”、“?abc?”、“??abc”之類的字串。
如果序列可以被蓋印,則返回一個數組,其中包含每一輪最左側被蓋印字母的索引。如果不可能,則返回一個空陣列。因此,當序列為“ababc”,印章為“abc”時,答案可以是 [0, 2],因為我們可以這樣形成: “?????” -> “abc??” -> “ababc”。
因此,如果輸入類似於 stamp = "abcd",target = "abcdbcd",則輸出將為 [3,0]
為了解決這個問題,我們將遵循以下步驟:
定義一個數組 ret
ok := true
n := 印章的大小
tsz := 0
當 ok 不為零時,執行以下操作:
ok := false
x := 0
對於初始化 sz := 印章的大小,當 sz > 0 時,更新(sz 減 1),執行以下操作:
對於初始化 i := 0,當 i <= 印章的大小,更新(i 加 1),執行以下操作:
newStamp := 一個長度為 i 的“*”字串 + 從索引 i 到 sz-1 的印章子字串 + 一個大小與印章大小相同的“*”字串
pos := target 中 newStamp 的索引
當 pos 存在於 target 中時,執行以下操作:
ok := true
x := x + sz
在 ret 的末尾插入 pos。
用“*”填充 target 從位置 pos 到 pos + 印章大小。
pos := target 中 newStamp 的索引
tsz := tsz + x
反轉陣列 ret
返回(如果 tsz 與 target 的大小相同,則返回 ret,否則返回一個空陣列)
讓我們看看下面的實現,以便更好地理解:
示例
#include <bits/stdc++.h> using namespace std; void print_vector(vector<auto> v){ cout << "["; for(int i = 0; i<v.size(); i++){ cout << v[i] << ", "; } cout << "]"<<endl; } class Solution { public: vector<int> movesToStamp(string stamp, string target) { vector<int> ret; bool ok = true; int n = stamp.size(); int tsz = 0; while (ok) { ok = false; int x = 0; for (int sz = stamp.size(); sz > 0; sz--) { for (int i = 0; i <= stamp.size() - sz; i++) { string newStamp = string(i, '*') + stamp.substr(i, sz) + string(stamp.size() - sz - i, '*'); int pos = target.find(newStamp); while (pos != string::npos) { ok = true; x += sz; ret.push_back(pos); fill(target.begin() + pos, target.begin() + pos + stamp.size(), '*'); pos = target.find(newStamp); } } } tsz += x; } reverse(ret.begin(), ret.end()); return tsz == target.size() ? ret : vector<int>(); } }; main(){ Solution ob; print_vector(ob.movesToStamp("abcd", "abcdbcd")); }
輸入
"abcd", "abcdbcd"
輸出
[3, 0, ]