[kuangbin带你飞] - F. Power Strings POJ - 2406 (Next简单理解)

题目链接 专题十六 KMP - F - Power Strings POJ - 2406

题意

给你一个字符串,让你找到一个子序列a,使字符串由a多次循环拼接得到。求循环的最多次数,及求a的最小长度。

思路一

我刚开始没有什么思路,后来想通过分解质因子来入手,毕竟这个字符串如果是由a多次拼接得到的,那么它一定是a.length的倍数。Next的数组还是一定要求的,里面存了一个最大前后缀,一定会对我的求解有帮助的。但是,不知为什么,得到的代码一直都WA。于是我开始了别的规律寻找。。。。。。


思路二

处于对Next数组的好奇,我开始对其进行探索,发现了一个规律,如果它符号题目条件,那么最后的一些数据必定会处于d为1的递增序列。而且最后位的Next必定是整个函数中最大(严格)的元素。

这样就很简单了,我用代码简单实现了这个规律后就AC了。但是Next数组远远没有这么简单。。。。。。

这里写图片描述


思路三

next数组关于循环节几个小应用

(1)i - next[i] 最小循环节(第一个字母开始)

(2)next[i] 最大循环节中的第几位数(此时循环节可交叉)

(3)next[i] != 0 && i % (i - next[i]) == 0,当前是循环节中的最 后一位.

(4)在(3)的前提下 i / (i - next[i]) 表示的最大周期个数,也就是在最小循环节的前提下的最大周期个数。


代码

#include 
#include 
#include 
using namespace std;

const int MAXN = (int)1e6+7;
const int INF = (int)0x3f3f3f3f;

int Next[MAXN];
char sub[MAXN];
int len;

void MakeNext(){
    Next[0] = 0;
    for (int i = 1,k = 0;i < len;i ++){
        while (k > 0 && sub[i] != sub[k])
            k = Next[k-1];
        if (sub[i] == sub[k]) k ++;
        Next[i] = k;
    }
}

int main()
{
    ios::sync_with_stdio(false);//scanf("%s",sub)
    while (cin >> sub,sub[0] != '.'){
        len = strlen(sub);
        MakeNext();

        int mn = -INF;
        int ans = 0;
        for (int i = 0;i < len;i ++){
            if (Next[i] > mn){
                ans = 0;
                mn = Next[i];
            }else if (Next[i] == mn){
                ans ++;
            }
        }

        if (mn == Next[len-1] && ans == 0) {
            int L = len-Next[len-1];
            if (len%L == 0)cout << len/L << endl; //printf("%d\n",len/L); //
            else           cout << 1 << endl; //printf("1\n"); //
        }else {
            cout << 1 << endl; //printf("1\n"); //
        }
    }
}

大神代码 根据思路三

#include 
#include 
char s[1000005];
int num[1000005];
int main()
{
    int n,case1=1;
    while(scanf("%s",s),s[0]!='.')
    {
        int j=-1;
        num[0]=-1;
        n=strlen(s);
        for(int i=0;iif(j==-1||s[i]==s[j])num[++i]=++j;
            else j=num[j];
        }
        if(n%(n-num[n])==0)
        printf("%d\n",n/(n-num[n]));
        else puts("1");
    }
    return 0;
}

你可能感兴趣的:(kuangbin带你飞,KMP,SA)