HDU3746 Cyclic Nacklace(KMP next陣列的應用)
題意:給出一個字串,任務為將其擴充套件為其迴圈節的整數倍。輸出需要補上的珠子的數目。只能在最左邊和最右邊補。
樣例解釋:aaa,以a為迴圈節,該鏈子已經滿足要求。
abca,以abc為迴圈節,需要補上bc,組成abcabc。
abcde,只能以自己為迴圈節,補上abcde,組成abcdeabcde。
解法:首先要理清楚思路。不管前面的next天花亂墜,012312101之類的,但是我們只關心最後一個的next,因為我們是從這裡開始補起來的。
主要考查的是next的運用。假設字串長度為len,那麼如果next[len]處為0,則說明沒有迴圈節,直接輸出其長度len即可。如abcde。
否則,我們就把(len-next[len])作為迴圈節,然後在最後一個開始補,顯然補(len-next[len])- next[len] %(len-next[len])即可。如abababa,next為
-10012345,我們就把ab作為迴圈節,補上b即可,上面的運算就是(7-5)-5%(7-5) = 1。
再考慮一下特殊情況,比如aaa,next為-1012,此時算出來為(3-2)-2%(3-2)=1,問題出在哪裡呢?顯然此時的答案等於迴圈節長度,加上一個迴圈節長
度的字元是無用的,我們應該再對答案對迴圈節長度取一次模。
程式碼:
#include<bits/stdc++.h> using namespace std; const int maxn = 2e5 + 5; int nex[maxn]; void Find(char *p, int len) { nex[0] = -1; for(int i = 0, j; i < len; ++i) { j = nex[i]; while(j != -1 && p[i] != p[j]) { j = nex[j]; } nex[i + 1] = j + 1; } } char str[maxn]; int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); #endif ios::sync_with_stdio(0); int T; cin >> T; while(T--) { cin >> str; int len = strlen(str); Find(str, len); if(nex[len] == 0) { cout << len << endl; } else { int t_len = len - nex[len]; cout << (t_len - nex[len] % t_len) % t_len << endl; } } return 0; }