Next數組求法
不用初始化,因爲Next數組是遞推出來的。用法爲getFail(s,strlen(s)).
const int MAX_N=101000;
char str[MAX_N],pattern[MAX_N];
int Next[MAX_N];
void getFail(char *p,int plen){
int i;
Next[0]=0;Next[1]=0;
for(i=1;i<plen;i++){
int j=Next[i];
while(j&&p[i]!=p[j])
j=Next[j];
Next[i+1]=(p[i]==p[j])?j+1:0;
}
}
囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖
學習筆記
KMP的Next數組可以求一個字符串的最小循環節,如果它有的話。
循環節長度 x=len-Next[len]。
比如ababab,x爲2
abbcabbcabbc,x爲3
但是如果是abba的話x爲3,如果想要求這個字符串的最小循環節長度再加一個判斷條件即可,
即如果len%x!=0的話x=len。
像abba,x應該爲len,即爲4.
像abbabba,x應該爲7,abbabbab,x爲8,abbabbabb,x爲3,因爲它可以整除了。
另一個問題,如果一個字符串,我最少需要添加多少個字符纔可以出現2個及以上的循環。
添加字符之後的字符串的最小循環節長度爲len-Next[len]。
那麼答案即爲(len-Next[len])-len%(len-Next[len])。
可以看成(循環節)-字符串長度%(循環節)。
定理:如果一個字符串有循環節的話且循環節且總長度可以整除循環節,即沒有末尾循環節破損,那麼最小循環節長度爲len-Next[len],如果循環節破損,那麼在沒法添加字符的條件下最小循環節長度即爲字符串本身長度len,而在可以添加字符的條件下,如果想要添加字符串數量最少,那麼添加完之後字符串的最小循環節爲len-Next[len]。
囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖囖
利用Next數組求字符串的前綴在字符串中出現的次數。
利用dp,dp[i]代表字符串的第1個字符到第i個字符這個子串出現在字符串中的次數(字符串下標從1開始,方便),這個出現次數是可重複的,比如aaaaa的dp[2]爲4。
dp數組求法
int len=strlen(s);
getFail(s,len);
for(i=1;i<=len;i++)
dp[i]=1;
for(i=len;i>=1;i--)
dp[Next[i]]+=dp[i];
小思維:
求字符串a的每個前綴在b中出現的次數。
可以把構建一個字符串c=a+’#’+b,然後求出dp_c,然後再求出dp_a,那麼答案就爲dp_c[i]-dp_a[i]。