注:この記事は人々KMPの次のアレイに用が理解するのではなく、明らかです!!新しい萌えの基礎を理解してください!!
Baiduのを見つけ、(実際には理解できるが、私はあまりにも料理だったはずです)私はブルーブック(劉Rujiaトレーニングガイド)KMPで学んで見えますが、ブルーブックは詳細に入るが、のは、百度をチェックし、コードを貼り付けることはできませんでした4つのブログがあまりにも理解して見えるが、少し考えを学ぶことがなかった見ました。
だから私は、コードに対する意義をNEXしたい、その後、庭の外に2時間を過ごしました。。。コードは、私の理解(派生)にコメントやあなたが私のプライベートな手紙を読むことができない場合はノックアウト。
私はちょうどKMPの絶望を感じていたときからです。。。私はあなたが人が同じ悩みを持って助けることができると思います。
PS:注釈\((... B)= (C ... D)\) を表し
\(T [A] = P [C]、\)
\(T [A + 1] = P [C + 1]、\)
\(。\)
\(。\)
\(。\)
\(T [B-1] = P [D-1]、\)
\(T [B] = P [D]。\)
(で\(getfail \) TがPです)
#include <iostream>
#include <cstdio>
#include <cstring>
//其实只是为了用strlen而已
using namespace std;
#define reg register
const int N = 1e6+5, INF = 1e9;
char T[N], P[N];
int lt, lp;
int nex[N]; // nex[0]=0
// nex[1]=x1 -> 0...x1-1=1-x1...1-1 (其实就是前缀与后缀,看了几个人的博客都有提到这个概念)
// nex[2]=x2 -> 0...x2-1=2-x2...2-1
// .
// .
// .
// nex[n]=xn -> 0...xn-1=n-xn...n-1(@0) =>
// if n,i faild -> compare xn,i (@1) 在这里显然@0与@1互为充要条件(似乎表述有问题??算了那是数学上的事情。就是说两个是可以互推的)
inline void getfail() { //其实就是用模板匹配模板
int j = 0; //j -> 模板的下标 i -> 待匹配字串的下标(这里就是模板) (@2)
for (reg int i = 1; i < lp; ++i) {
// j=0 -> compare P[i], P[0] -> 从头开始 => =>//
// 1.P[i]!=P[0] -> compare P[++i], P[0] -> (j=0)not change =>//
// 2.P[i]==P[0] -> compare P[++i], P[1(++j)] -> ++j =>//
// =>//
// j>0 -> compare P[i], P[j] -> {*}={0...j-1==i-j...i-1} => =>//
/* 1.P[i]!=P[j] -> (@1) (@2) -> =>// =>//
compare nex[j],i => =>// =>//
(1).P[nex[j]]!=P[i] -> (@1) (@2) -> =>// =>//
compare nex[nex[j]],i =>// j=nex[j] =>//
. =>// =>//
. =>// =>//
. =>// =>//
2.P[i]==P[j] -> compare i+1,j+1 => ++j =>//
*/
while (j && P[i] != P[j]) j = nex[j];
// 1.P[i]==P[j] => (though j==0) (这里可以推出两点)
// (1)0...j=i-j...i -> (@0) -> nex[i+1]=j+1
// (2)compare ++j,++i -> ++j
// => ++j, nex[i+1]=j (因为for循环中有++i)
// 2.P[i]!=P[j] -> j==0 (注意while里的条件) -> when i+1!=x 从头开始
// (因为P[i]与P[0]也不相等所以如果i+1失配了那么就只能从模板的第一个开始匹配) =>
// compare i+1,0 -> (@0) -> nex[i+1]=0 (j)
if (P[i]==P[j]) ++j;
nex[i+1] = j;
}
}
inline void KMP() {
getfail();
int j = 0;
for (reg int i = 0; i < lt; ++i) {
// most same as getfail()
while (j && T[i] != P[j]) j = nex[j];
// 1.j==lp-1 -> success -> print(i-lp+1) 匹配成功
// 2.T[i]==P[j] -> compare i+1,++j 如果相等就应该继续比较P[i+1]与P[j]
// 3.T[i]!=P[j] -> j=0 -> (@0) -> compare i+1, 0(就是j)
if (T[i] == P[j]) ++j;
if (j == lp) printf("%d\n", i-lp+1+1);
}
}
int main() {
scanf("%s %s", T, P);
lt = strlen(T), lp = strlen(P);
KMP();
for (reg int i = 1; i <= lp; ++i) { //洛谷P3375 要求输出但却没有规定next数组,毕竟每个人的模板不同,在观察之下我发现似乎就是这样结果AC了。。。
printf("%d ", nex[i]); //这在KMP里不是重点啦所以不用纠结这一块QWQ
} //似乎是有大佬用hash做出来了%%%
putchar('\n');
return 0;
}
実際には、これはMPのようです、KMPは、アレイの最適化(トレーニングマニュアルのP213を)NEXする必要がありますが、MPは、時間の複雑さの下限値に達しており、同時に使用するのに十分なので、Baiduの聖歌の学生のアイデア。
実際に、私はそれが(私は根本的な原因を行います派生し、独自の方法に慣れているいくつかの主要なジュニアレースに従事することができる)あまり効率的かもしれないが、これも試すことができます学ぶための方法だと思います
また、3Dの大きなセットは(面白い)ステレオイヤータイプのヘッドフォンを囲んで示していノイズの多い環境の部屋に私のヘッドフォンがなければ私は単にQWQを考えるために停止することはできません。
\ [\ 2019年10月10日でUPD \ \]
最適話すの下では、方法は、ブログはここに移動しました。
実際には、我々はすでにあなたがそれを飛び越えることができますので、不一致を知っているが、いくつかの問題が出て、内に直接ジャンプすることはできませんのでご注意ときの$ NXT $とは同じ、そして不一致を所有している場合、このような統計的なプログラムの特定の数など。
だから、コードがあります
if (P[now] == P[i + 1]) nxt[i + 1] = nxt[now];
else nxt[i + 1] = now;
同様に(最後のポイント後の時間、成功した試合という)最後の項については、彼の$ NXT $が最適化されていない、一定の判断の条件が満たされていないが、複数のデータセットが、それは条件をクリアしていないにつながる可能性があり結果は$ NXTで、設定[LP] $が最適化されています。これは、その点を留意すべきです。