並不對勁的字串專題(二) kmp

2022-05-08 20:30:08 字數 2663 閱讀 3394

據說這些並不對勁的內容是《資訊學奧賽一本通提高篇》的配套練習。

先感嘆一句《資訊學奧賽一本通提高篇》上對kmp的解釋和matrix67的部落格相似度99%(還抄錯了),莫非matrix67藏在編者之中?

但這不重要,因為並不對勁的人不會對kmp作出任何解釋。

課後練習:

1.bzoj1355->

可以將題目中給出的字串看成形如這樣的串:

那麼,對於其中的某一位:

它到當前字首的第二個迴圈節的開始組成的子串和字首相等:

所以,對於當前位置x,fail[x]就是它到當前字首的第二個迴圈節的開始組成的子串的長度,x-fail[x]就相當於字串的開始到當前字首的第二個迴圈節的開始的長度,也就是乙個迴圈節的長度:

但是,隨著x增大,x-fail[x]不降,所以對於長度為n的串,答案就是n-fail[n]。

**就是求fail指標就行了。

#includeusing namespace std;

#define maxn 1000010

int fa[maxn],n,ans;

char s[maxn];

int main()

printf("%d",n-fa[n]);

return 0;

}

2.bzoj1511->

並不能讀懂題面,求大佬幫助。

3.bzoj3620->

題目中要找形如a+b+a的子串,所以可以列舉左端點,再算出每個右端點是否可行。

首先,固定左端點後,求出fail指標。對於fail[x]*2

對於fail[x]*2>=x的呢?會發現,1到fail[x]的子串和x-fail[x]+1到x的子串一樣,1到fail[fail[x]]的子串和fail[x]-fail[fail[x]]+1到fail[x]的子串一樣,所以1到fail[fail[x]]的子串和x-fail[fail[x]]+1到x的子串一樣。那麼就可以順著fail指標往上找,直到長度*2不斷順著fail指標往上找的過程聽上去很暴力,這題本來就很暴力了,就要避免這種暴力的。發現對於點x求出合法解為y後,對於x在fail樹所有子孫,就都是合法的了。那麼可以標記x,這樣計算x在fail樹所有子孫時,走到x就可以停了。

這個優化聽上去很扯,它還是o(n2)的,但是15000的資料還是過了,是因為kmp常數小的緣故?

#include#include#include#include#include#include#include#include#include#include#include#define maxn 15010

using namespace std;

int read()

void write(int x)

if(x<0)

while(x)ch[++f]=x%10+'0',x/=10;

while(f)putchar(ch[f--]);

putchar('\n');

}int ans,k,fa[maxn],n,lst[maxn];

char s[maxn];

void rebuild()

for(int i=1;i<=n;i++)

//cout<=k) lst[i]=u,ans++;

//cout<4.bzoj3942->

先想乙個比較暴力的:讓乙個指標k從頭往後掃s,每次判斷長度為|t|的字尾是否等於t。

這個的時間複雜度是o(|s|*|t|),發現判斷長度為|t|的字尾是否等於t有點像kmp。

那麼就可以再維護乙個指標p,表示t中走到的位置。對於s的每一位,開乙個陣列記錄k走到這裡時p走到的位置。

每當p走到t的結尾時,k退回|t|前的位置,p變成之前記錄的k走到該點時p的位置。

#include#include#include#include#include#include#include#include#include#include#include#define maxn 1000010

using namespace std;

char s[maxn],t[maxn];

int fa[maxn],mat[maxn],top,ns,nt,ans[maxn];

void go(int & u,char c)

if(t[u+1]==c)u++;

else u=0;

}int main()

int u=0;

for(int i=1;i<=ns;i++)

}//for(int i=1;i<=ns;i++)cout<

for(int i=1;i<=top;i++)putchar(s[ans[i]]);

return 0;

}

並不對勁的splay

splay和不加任何旋轉一定會被卡的二叉搜尋樹的唯一區別就是每次操作把當前節點旋轉到根。旋轉有各種zig zag的組合方式,感覺很麻煩,並不對勁的人並不想講。其實可以找出一些共性將它們合併。設ls a 點a是其父親的左兒子 son a 0 a的左兒子,son a 1 a的右兒子,fa a a的父親。...

並不對勁的費用流

最小費用最大流肯定要保證最大流,所以它和最大流有一些類似的性質。如果把費用看成邊,就可以每次走最短路 保證費用最小 走到不能走為止 保證最大流 費用流版的ek就是這樣。需要注意的是,反向弧的邊權為它對應的正向弧的費用的相反數,所以最短路要用spfa來求。費用流版的dinic,又叫zkw費用流,還是多...

並不對勁的字尾陣列

字尾陣列sa x 表示排序後第x位在排序前的位置。這個東西的求法有兩種,一種是倍增,時間複雜度o n log n 或o n log2n 另一種是用不知道什麼方法做到的o n 至於第二種方法是什麼,並不對勁的人並不知道,所以只說倍增。考慮正常地比較兩個字串,都是從頭比較到尾 那麼,如果把兩個字串都斷成...