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; }