給定乙個字串,問最多是多少個相同子串不重疊連線構成。
kmp的next陣列應用。這裡主要是如何判斷是否有這樣的子串,和子串的個數。
若為abababa,顯然除其本身外,沒有子串滿足條件。而分析其next陣列,next[7] = 5,next[5] = 3,next[3] = 1,即str[2..7]可由ba子串連線構成,那怎麼否定這樣的情況呢?很簡單,若該子串滿足條件,則len%sublen必為0。sunlen可由上面的分析得到為len-next[len]。
因為子串是首尾相接,len/sublen即為substr的個數。
若l%(l-next[l])==0,n = l/(l-next[l]),else n = 1
#include#includeusing namespace std;
char pattern[1000002];
int next[1000002];
/*kmp演算法,需要首先求出模式串的next函式值
next[j] = k,說明 p0pk-1 == pj-kpj-1,也就是說k為其前面相等串的長度
*/void get_nextval(const char* pattern)
else
j=next[j]; //若j值不相同,則j值回溯
}}//get_nextval
int main(void)
return 0;
}
大意:定義字串a,若a最多由n個相同字串s連線而成,則a=s^n,如"aaa" = "a"^3,"abab" = "ab"^2
"ababa" = "ababa"^1
給出乙個字串a,求該字串的所有字首中有多少個字首sa= s^n(n>1)
輸出符合條件的字首長度及其對應的n
如aaa
字首aa的長度為2,由2個'a'組成
字首aaa的長度為3,由3個"a"組成
分析:kmp
若某一長度l的字首符合上訴條件,則
1.next[l]!=0(next[l]=0時字串為原串,不符合條件)
2.l%(l-next[l])==0(此時字串的長度為l/next[l])
對於2:有str[0]....str[next[l]-1]=str[l-next[l]-1]...str[l-1]
=》str[l-next[l]-1] = str[l-next[l]-1+l-next[l]-1] = str[2*(l-next[l]-1)];
假設s = l-next[l]-1;則有str[0]=str[s]=str[2*s]=str[3*s]...str[k*s],對於所有i%s==0,均有s[i]=s[0]
同理,str[1]=str[s+1]=str[2*s+1]....
str[j]=str[s+j]=str[2*s+j]....
綜上,若l%s==0,則可得l為str[0]...str[s-1]的相同字串組成,
總長度為l,其中字串長度sl = s-0+1=l-next[l],迴圈次數為l/sl
故對於所有大於1的字首,只要其符合上述條件,即為答案之一
#include#include#includeusing namespace std;
char pattern[1000002];
int next[1000002];
/*kmp演算法,需要首先求出模式串的next函式值
next[j] = k,說明 p0pk-1 == pj-kpj-1,也就是說k為其前面相等串的長度
*/void get_nextval(const char* pattern)
else
j=next[j];
}}//get_nextval
int main(void)
printf("\n");
}return 0;
}
大意:給出乙個字串a,求a有多少個字首同時也是字尾,從小到大輸出這些字首的長度。
分析:kmp
對於長度為len的字串,由next的定義知:
a[0]a[1]...a[next[len]-1]=a[len-next[len]]...a[len-1]此時a[0]a[1]...a[next[len]-1]為乙個符合條件的字首
有a[0]a[1]....a[next[next[len]]-1] = a[len-next[next[len] - next[next[len]]]...a[next[len]-1],故a[0]a[1]....a[next[next[len]]-1]也是乙個符合條件的字首
故從len=>next[len]=>next[next[len]] ....=>直到某個next為0均為合法答案,注意當首位單詞相同時,也為答案。
#include#include#include#includeusing namespace std;
char pattern[400002];
int next[400002];
/*kmp演算法,需要首先求出模式串的next函式值
next[j] = k,說明 p0pk-1 == pj-kpj-1,也就是說k為其前面相等串的長度
*/void get_nextval(const char* pattern)
else
j=next[j];
}}//get_nextval
int main(void)
if(pattern[0]==pattern[n-1]) //首部、尾部字元相同
ans.push_back(1);
i=ans.size()-1;
for(;i>0;i--)
printf("%d ",ans[i]);
printf("%d\n",ans[0]);
} return 0;
}
KMP演算法詳解及各種應用
kmp演算法詳解 kmp演算法之所以叫做kmp演算法是因為這個演算法是由三個人共同提出來的,就取三個人名字的首字母作為該演算法的名字。其實kmp演算法與bf演算法的區別就在於kmp演算法巧妙的消除了指標i的回溯問題,只需確定下次匹配j的位置即可,使得問題的複雜度由o mn 下降到o m n 在kmp...
KMP演算法及應用
kmp演算法用來解決一系列字串單模式匹配問題,其以難理解,難記憶著稱。其next陣列的構造就如同ac自動機中的fail指標,就是如果匹配失敗,字串應從 開始繼續匹配。這裡的next陣列表示 next i 前i個字元的公共最長前字尾長度。覺得對於kmp演算法,這篇寫的不錯 現在來講一下應用。給定兩個字...
KMP詳細解釋及KMP演算法模板
kmp是什麼,kmp解決什麼型別的問題 kmp全稱為knuth morris pratt演算法,是一種高效的字串匹配演算法,尋找乙個字串中是否包含另乙個字串,例如 char s ababababcab char p ababc s為模板串 主串 p為子串,在s中找到p的位置 暴力匹配演算法 o n ...