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

猜你喜欢

转载自www.cnblogs.com/llzhh/p/10247060.html