記乙個kmp演算法的應用,經典的kmp演算法詳解還是看這裡
問題:給乙個串,求這個串前i位構成的字首由多少個子串組成。
比如aabaabaabaab,前2位是aa,a重複了2次,前6位是aabaab,aab重複了2次,前9位是aabaabaab,aab重複了3次,前12位是aabaabaabaab,aab重複了4次。
先說一下next()函式。pre[i] = j表示 s[1...j] = s[i - j....i];
下面討論當i % (i - pre[i]) == 0 時,例如i = 12, pre[12] = 9:
如圖。s[1...9] == s[3...12];
因為已知 i % (i - pre[i]) == 0; 那麼把i分成 i / (i - pre[i])段。
已知:s3 == t3;
s2 == t2;
s1 == t1;
又因為t3 == s2, t1 == s1。所以 t1 = t2 = t3 = s1 = s2 = s3,也就是說 i / (i - pre[i])這幾段中每一段都相等。
現在回到原問題:求這個串前i位構成的字首由多少個子串組成,只需要找到i / (i - pre[i]) == 0的點i,則共有 i / (i - pre[i])個相同的子串構成字首s[1...i]。
練習:poj 1961, poj 2406
附1961的**:
#include #include#include
#include
#include
#include
#include
#define cl(arr, val) memset(arr, val, sizeof(arr))
#define rep(i, n) for(i = 0; i < n; ++i)
#define for(i, l, h) for(i = l; i <= h; ++i)
#define ford(i, h, l) for(i = h; i >= l; --i)
#define l(x) x << 1
#define r(x) x << 1 | 1
#define mid(l, r) (l + r) >> 1typedef
long
long
ll;using
namespace
std;
const
int n = 1000010
;char
s[n];
intpre[n];
int dp[n]; //
這裡加了乙個陣列,記錄到i位置時所構成的字首由多少個子串組成。
intn;
void
next()
}int
main()
}cout
<
}return0;
}
KMP演算法中的next函式
kmp演算法詳解看 next i 表示當模式串t i 與主串失配時,模式串的索引回溯到next i 主串的索引不變 下面串的下標均從0開始 1 i 0 next i max k 0 k 證明模式串next函式的可行性 當t i 與 s j 失配時,即 t i s j 時 可得t 0.i 1 s j ...
KMP演算法的next函式詳解
不得不說,kmp的next函式是在是難以理解,智商拙計。在幾天的斷斷續續理解之後一度想放棄,在得知了它的別名看毛片後重新提起了興趣。kmp演算法理解的難點在於next遞推的理解,也就是說當next j k的時候,如何求出next j 1 的值。先解釋一下next j k的意義。這說明在子串中該j位置...
KMP演算法中next函式的解析
今天花了半天的時間,終於把kmp演算法中的next函式整明白了 先看看next資料值的求解方法 位序 1 2 3 4 5 6 7 8 模式串 a b a a b c a c next值 0 1 1 2 2 3 1 2next陣列的求解方法是 1.第一位的next值為0 2.第二位的next值為1 後...