[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

 

转载于:https://www.cnblogs.com/xutianshu/p/10185733.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值