UVALIVE 3026 Period(kmp)

来源:互联网 发布:查询域名是否已备案 编辑:程序博客网 时间:2024/05/16 15:23

思路:KMP算法。还记得KMP算法中next数组的含义吗。假设next[i]=x,就表明字符串前i个字符的子串中前x个字符和后x个字符是完全相同的。对于一个周期串来说,假设它的长度是len,最小周期是p,那么它的前len-p个字符和后len-p个字符是完全相同的。那么我们只需要求一次next数组,就可以掌握字符串的所有前缀的周期情况了。


这里的next的求法就是最原始的那种,没有优化,因为他是比较自身循环次数,所以不需要进行优化去除不匹配的特殊情况


#include<iostream>#include<cstdio>#include<cstring>#include<string>using namespace std;const int maxn=1000000+5;int next[maxn];int num;void getnext(string p){    int plen=p.size();    int k=-1;    int j=0;    next[0]=-1;    while(j<=plen-1)    {        if(k==-1||p[j]==p[k])        {            j++;            k++;                next[j]=k;        }        else            k=next[k];    }}int n;void zhuan(string in){     for(int i = 1; i < n; i++)//动态规划求next数组    {        int j = i;        while(j != 0)        {            j = next[j];            if(in[j] == in[i])            {                next[i + 1] = j + 1;                break;            }        }    }}int main(){    string s;    int n;    int k=0;    while(cin>>n&&n)    {        cin>>s;        k++;        getnext(s);       // for(int i=0;i<n;i++)        //    cout<<next[i]<<endl;        //zhuan(s);       // for(int i=0;i<n;i++)        //    cout<<next[i]<<endl;        cout<<"Test case #"<<k<<endl;        for(int i=0;i<=n;i++)        {            if(i%(i-next[i])==0&&next[i]&&i/(i-next[i])>=2)                cout<<i<<" "<<i/(i-next[i])<<endl;        }        cout<<endl;    }    return 0;}

但是用next应该会报CE

改成了nextt


其实kmp还是蒙蒙的,所以升级版ac自动机过几天再补