KMP算法及应用

KMP算法用来解决一系列字符串单模式匹配问题,其以难理解,难记忆著称。其next数组的构造就如同AC自动机中的fail指针,就是如果匹配失败,字符串应从哪里开始继续匹配。这里的next数组表示:next[i]=前i个字符的公共最长前后缀长度。觉得对于KMP算法,这篇写的不错——http://www.cnblogs.com/c-cloud/p/3224788.html。

现在来讲一下应用。

给定两个字符串a和b,我们可以定义一些操作:a*b为将字符串a和字符串b连接起来,比如a= "aoe",b= "jkw",那么a*b= "aoejkw"。进一步,我们可以有指数操作,a^0= "", a^1=a, a^2=a*a, a^n=a*(a^(n-1))=a*a*…*a (n个a)

现在给你一个字符串,你可以将它看成是a^n的形式,比如字符串"abababab",可以认为是"abab"^2, 也可以是"abababab"^1,还可以是"ab"^4。

现在问题是,给定的字符串,我们想让它变成a^n中的n达到最大,那么这个n最大是多少?例如:"abababab"最大的n是4。

 

输入

第一行,一个整数m,表示有m个字符串。

接下来m行每行输入一个只含小写字母的字符串。

 

输出

输出m行,对于每行输出相应字符串的最大n。

 

样例输入

3
abcde
aaaaaa
abababab

样例输出

1
6
4

提示

这道题一看觉得不是特别会,暴力算法老王的bloghttp://www.cnblogs.com/TUncleWangT/p/7162665.html讲了,正解就是运用了KMP算法里的next数组。我们令原字符串长度为S,重复字符串长度为T,则S=K*T,由定义可知next[S]=(K-1)*T;所以S-next[S]=T,判断一下整除就好了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
char str[1000005];
int next[1000005];
void make_next()
{
    int len=strlen(str),q,k;
    next[0]=0;
    for(q=1,k=0;q<len;q++)
    {
        while(k>0&&str[q]!=str[k])
        {
            k=next[k-1];
        }
        if(str[k]==str[q])
        k++;
        next[q]=k;
    }
}
void Debug()
{
    int len=strlen(str);
    for(int i=0;i<len;i++)
    cout<<next[i]<<' ';
}
void work()
{
    int tmp=strlen(str)-next[strlen(str)-1];
    if(strlen(str)%tmp==0) cout<<(strlen(str)/tmp)<<endl;else cout<<1<<endl;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",str);
        make_next();
        work();
    }
}

 

posted @ 2017-07-29 10:18  dancer16  阅读(1715)  评论(0编辑  收藏  举报
描述