給你乙個主串str
strst
r以及n
nn個模式串。問你這n
nn個模式串的所有迴圈同構在主串str
strst
r中的出現次數。
這是乙個需要轉換思維的題目。
首先,如果題目中不要求我們求每乙個模式串的迴圈同構的出現此時,顯然這道題我們直接可以用字尾自動機進行求解。而現在的問題就是我們應當如何在比較優的時間內將乙個字串中的所有迴圈同構的出現次數。
我們首先對主串建立字尾自動機。
其次,我們考慮將模式串str
strst
r複製並接在原串後面,形成乙個新串str
st
rstrstr
strstr
,這樣,新串中的每乙個長度等於∣st
r∣
|str|
∣str
∣的子串都可以表示為串str
strst
r的其中乙個迴圈同構子串。此時,我們發現,如果我們用新串str
st
rstrstr
strstr
在字尾自動機上匹配,匹配到的每個長度為∣st
r∣
|str|
∣str
∣的子串出現次數之和即為答案。因此,在我們在字尾自動機上對str
st
rstrstr
strstr
串進行匹配的過程中,我們只需要記錄一下當前成功匹配的長度。倘若當前成功匹配的長度大於∣st
r∣
|str|
∣str
∣,則我們只需要在par
en
tparent
parent
樹上跳轉,直到出現乙個狀態sti
st_i
sti
,使得len
[sti
]+1≤
∣str
∣len[st_i]+1\le|str|
len[st
i]+
1≤∣s
tr∣,此時我們只需要把該狀態sti
st_i
sti
所對應的所有子串的出現次數∣en
dpos
(sti
)∣
|endpos(st_i)|
∣endpo
s(st
i)∣
累加到答案即可。
而某狀態sti
st_i
sti
所對應的所有子串的出現次數∣en
dpos
(sti
)∣
|endpos(st_i)|
∣endpo
s(st
i)∣
,我們可以用拓撲排序在建立自動機的過程中預處理出來。
ps:字尾自動機要開雙倍/四倍空間,否則會瘋狂re
#include
using
namespace std;
const
int maxn =
1000000
;char str[maxn]
;int n,ans[maxn]
;struct sam
void
clear()
void
init
(char
*s)}
void
insert
(int c)}}
void
build
(char
*s)}
void
query
(int len,
int id)
if(i>len&&l>=len)
}printf
("%d\n"
,ans);}
}sam;
intmain()
sam.
query
(len,i);}
}
Codeforces 587C 樹上倍增
題意 求樹上兩點路徑中的前 a 10 小的點權值。思路 類似lca倍增演算法來儲存 i 2 j 路上的 前 10 小個 的點權值。然後要寫乙個權值合併 具體求 u v 的話,就是先分別計算 和 減1是lca會重疊 然後再合併,輸出答案。include include include include ...
Codeforces 976C 題解報告
對資料進行排序 1 按左邊的數從小到大排 2 若左邊的數相等,則按右邊的數從大到小排。排序之後,若乙個數的右邊的數小於等於上乙個數的右邊的數,則這兩個數必然符合題意。比如2 13 2 12 1 11排序之後,變為 1 11 2 13 2 12因為12 13,則有 2,12 被包含在它的上乙個數 2,...
CodeForces 948C 解題報告
題目鏈結 這道題看出來了是一道stl題,本來一開始用佇列去做,結果tle,在這裡先給出tle include using namespace std typedef long long ll const int maxn 1e5 10 int n,v maxn t maxn int main els...