[POJ]poj1961,poj2406(KMP)

题意:求字符串的最小循环节长度,一个只要求原字符串的,一个要求所有前缀串的。

考虑KMP算法中的next数组,next[i]+1表示使前缀后缀相等的最大长度,可以推知L=s.size()-next[i]-1为字符串的最小循环节长度。

当s.size()是L的整数倍时,L即是循环节长度,否则最后一个循环节不完整(如abcabca),答案只能是s.size()。

(问题:如何证明当x为最小循环节长度时,如果y不是x的倍数,循环节长度一定不能为y?)

两题都可以一遍getnext实现。O(n)

#include <iostream>
#include <string>

using namespace std;
const int N =1E6+7;
int nxt[N];

void getnxt(string s){
    int k=-1;
    nxt[0]=-1;
    for(int i=1;i<s.size();i++){
        while(k!=-1&&s[i]!=s[k+1])k=nxt[k];
        if(s[i]==s[k+1])k++;
        nxt[i]=k;
        int re=i+1-nxt[i]-1;
        if((i+1)%re==0&&re!=i+1)cout<<i+1<<" "<<(i+1)/re<<endl;
    }
}

int main()
{
   int x,cnt=0;
   string s;
   while(cin>>x){
        if(!x)break;
        cin>>s;
        cout<<"Test case #"<<++cnt<<endl;
        getnxt(s);
        cout<<endl;
   }
}
1961

 

#include <iostream>
#include <string>

using namespace std;
const int N =1E6+7;
int nxt[N];

void getnxt(string s){
    int k=-1;
    nxt[0]=-1;
    for(int i=1;i<s.size();i++){
        while(k!=-1&&s[i]!=s[k+1])k=nxt[k];
        if(s[i]==s[k+1])k++;
        nxt[i]=k;
    }
}

int main()
{
   string s;
   while(cin>>s){
        if(s[0]=='.')break;
        getnxt(s);
        int re=s.size()-nxt[s.size()-1]-1;
        if(s.size()%re)cout<<1<<endl;
        else cout<<s.size()/re<<endl;
   }
}
2406

 

posted on 2018-12-27 16:31  枫棠  阅读(180)  评论(0编辑  收藏  举报

导航