12年成都 e 貪心+kmp hdu 4468
重要的事情說在前面,以後kmp照這樣寫。
賽中的時候過的人不多,也沒有什麼具體的思路。發現問題可以轉化為最短字尾,使得前面的字串都是它的子串。甚至想著能不能列舉字尾,o(1)或者log的查詢。然後就走入死角了。
實際上還是字串的題目做的不夠多。如果是倒序遍歷的話,那查詢的字串操作也應該是倒序的,不存在乙個倒序乙個正序之說。再者,要檢測之前是否為其子串,最壞情況下需要把整個字串都遍歷一遍,也不存在可以log查詢的方法。
正解是貪心+kmp。過程就是如何構造最小的明文s。儲存乙個明文s,在向後遍歷的過程中,如果當前節點i不能與字串匹配,則從上一次記錄的last指標處,把密文中[last,i]都加入明文。最後輸出答案時,由於明文一定為字尾,所以之前產生明文可能出現最後字尾匹配完全、但是明文沒有遍歷完全的情況,這時候要把整個字尾都加入明文,答案為(密文長度-last指標+明文長度)。
那麼,問題來了。
1. 為什麼貪心的方法是這樣,而不是把每乙個不能匹配的字元單獨加入明文呢?
對於字串abcad,第四個a能與第乙個a匹配,d不能與任何乙個匹配。假設只是單獨把d加入明文,則明文為abcd,然後就發現這樣是不能構成字串abcad的。證畢。
2. 為什麼這樣貪心是正確的?
沒有很明確的證明方法,假設對於字串a-b-c(表示子串而不是字母),那麼如果a和b不匹配,肯定要把b整個加進去才能合法,不存在不加b就能合法的情況。換句話說,遇到不合法的子串,你可以選擇多加,但是這個子串一定要加入明文,而且多加的部分設為b,必要部分為a,如果後面出現a不匹配的情況,多加的b也是沒有任何作用的。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 1e5 + 5;
char s[maxn], t[maxn];
int f[maxn], cnt;
void add(int l, int r)
}int main()
else
if(j == -1)
// printf("i = %d, j = %d, last = %d, cnt = %d, s[i] = %c, s[j + 1] = %c\n", i, j, last, cnt, s[i], t[j + 1]);
//printf("f ");
//for(int k = 0 ; k < cnt ; k++) printf("%d ", f[k]);
//printf("\n");
}// printf("last = %d\n", last);
printf("case %d: %d\n", ++cas, n + cnt - last);
}return
0;}
11年成都網路賽
今天把去年成都的網路賽做了一下,去年是一題不會哇,現在也挺吃力,還有幾題不會,有空再來看 attack 樹狀陣列,這題樹狀陣列節點n記錄的是wall n 和wall n 1 被炮擊的差 include include include includeusing namespace std define...
11年成都網路賽
今天把去年成都的網路賽做了一下,去年是一題不會哇,現在也挺吃力,還有幾題不會,有空再來看 attack 樹狀陣列,這題樹狀陣列節點n記錄的是wall n 和wall n 1 被炮擊的差 include include include includeusing namespace std define...
2023年成都邀請賽解題報告
上海邀請賽前拿2013年的成都邀請賽熱身,比賽結果大大出乎了我們的預期啊。沒做出來的幾道題可能還會更新的。a題 水題。這題是我敲的。敲麻煩了。sad。你們就當沒看見吧。include include include include include using namespace std int ma...