1. 程式人生 > >POJ 2406 Power Strings(字尾陣列或KMP或擴充套件KMP)

POJ 2406 Power Strings(字尾陣列或KMP或擴充套件KMP)

題意:

給你一個字串求最多迴圈了多少次(這個題保證了最後一個迴圈節是完整的)

思路:

就是求最小迴圈節,這個問題可以用字尾陣列,KMP,擴充套件KMP都能做出來,不過我個人覺得求最小迴圈節還是擴充套件KMP最好寫了,KMP其次,字尾陣列搞這個反而有點多餘。。。不過既然論文提到了字尾陣列的寫法,那就寫寫好了
首先是擴充套件KMP,在求出擴充套件KMP的next陣列後,找到第一個next[i]+i==len且len%i=0的點,這個i就是最短迴圈節。
對於KMP,如果lennext[len]不為len且next[i]%(len-next[i])為0,那麼迴圈節就是lennext[le

n],否則最短迴圈節就是自身
對於字尾陣列,列舉長度,如果len%i==0且rak[0]-rak[i]==1且height[rak[0]]==len-i就是一個合格的解,然而這題居然卡倍增的做法,所以程式碼以後補上

錯誤及反思:

程式碼:

首先是擴充套件KMP的做法:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int maxn=1000100;
int anext[maxn];
char arr[maxn];
void getanext(char
*str) { int i=0,j,p=1,len=strlen(str); anext[0]=len; while(str[i]==str[i+1]&&i+1<len) i++; anext[1]=i; for(i=2;i<len;i++) { if(anext[i-p]+i<anext[p]+p) anext[i]=anext[i-p]; else { j=max(anext[p]+p-i,0); while
(i+j<len&&str[j]==str[j+i]) j++; anext[i]=j; p=i; } } } int main(){ while(scanf("%s",arr)&&arr[0]!='.') { getanext(arr); int len=strlen(arr); for(int i=1;i<=len;i++) { if(anext[i]+i==len&&len%i==0) { printf("%d\n",len/i); break; } } } }

然後是KMP的做法:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int len,nextval[1100000];
char w[1100000];
void get_next(){
    int j=0,k=-1;
    nextval[0]=-1;
    while(j<len){
        if(k==-1||w[k]==w[j])
            nextval[++j]=++k;
        else k=nextval[k];
    }
}
int main(){
    while(scanf("%s",w)){
        if(w[0]=='.') break;
        len=strlen(w);
        get_next();
        int l=len-nextval[len];
        if(l!=len&&nextval[len]%l==0)
            printf("%d\n",len/l);
        else printf("1\n");
    }
}