1. 程式人生 > >POJ-2406Power Strings-KMP+定理

POJ-2406Power Strings-KMP+定理

class space stream ace ngs mes div () nbsp

Power Strings

題意:給一個字符串S長度不超過10^6,求最大的n使得S由n個相同的字符串a連接而成,如:"ababab"則由n=3個"ab"連接而成,"aaaa"由n=4個"a"連接而成,"abcd"則由n=1個"abcd"連接而成。

定理:假設S的長度為len,則S存在循環子串,當且僅當,len可以被len - next[len]整除,最短循環子串為S[len - next[len]]

例子證明:
設S=q1q2q3q4q5q6q7q8,並設next[8] = 6,此時str = S[len - next[len]] = q1q2,由字符串特征向量next的定義可知,q1q2q3q4q5

q6 = q3q4q5q6q7q8,即有q1q2=q3q4,q3q4=q5q6,q5q6=q7q8,即q1q2為循環子串,且易知為最短循環子串。由以上過程可知,若len可以被len - next[len]整除,則S存在循環子串,否則不存在。

解法:利用KMP算法,求字符串的特征向量next,若len可以被len - next[len]整除,則最大循環次數n為len/(len - next[len]),否則為1。

我的ac代碼:

#include <cstring>
#include <iostream>
#include <cstring>
#include 
<string> #include <cstdio> using namespace std; string str; int len,nx[1000000+10]; void getnext() { int j = 0,k = -1; nx[0] = -1; while(j<len) { if(k==-1||str[j]==str[k]) { nx[++j]=++k; }else { k=nx[k]; } } }
int main(){ while(cin>>str) { if(str[0]==.)break; len = str.length(); getnext(); if(len % (len-nx[len]) == 0) { cout<<len/(len-nx[len])<<endl; } else cout<<1<<endl; } return 0; }

POJ-2406Power Strings-KMP+定理