字首函式的應用。
題目大意:我們都知道字首函式,但現在要求求出乙個更強大num
陣列一一對於字串s的前i個字元構成的子串,既是它的字尾同時又是它的字首,並且該字尾與該字首不重疊,將這種字串的數量記作num[i]。
其實只要找出最長符合要求字首即可,更短的一定是最長符合要求字首的字首,推字首函式時求乙個「字首」和就好(即累加到最長字首上)。如何求最長不重合既是字首又是字尾的串呢?字首函式求的會包含重合的,想一想最開始重合那個過程,在i-1的位置如i=7,在i=6的位置p[i]一定等於3,這樣i=7時才可能重合,重合時我們只需令j=p
[j−1
]j=p[j-1]
j=p[j−
1]即可。其他過程和求字首函式一樣,注意j設在外面,每次只用從上一次匹配的位置匹配,這樣每次重合也最多重合乙個字元,跳一會p[j-1]即可.
(啊,寫出來好不清晰,如果掌握了字首函式,這個還是可以想到的,至少最直觀可以想到一直跳p[j-1]至不重合,用倍增處理可以降低時間複雜度,然而還是80,看題解有用倍增過的,還只是改了陣列一維和二維的位置,好神奇。
#includeusing namespace std;
const int maxn=1e6+5;
const int mod=1e9+7;
typedef long long ll;
int p[maxn],z[maxn],np[maxn],num[maxn],f[maxn][21];
char s[maxn];
void getpi(int n)
}if(j)
j=f[j][0];*/
if(j)
np[i]=1+num[j-1];
else np[i]=0;
}ll ans=1;
for(int i=0;i 寫了一遍忘儲存了!
利用字首函式來容斥。要點:字串雜湊,把字串所有字尾用map儲存並對應好個數,那麼列舉所有字串所有字首,計算對應個數,對應該字首其長度為其字首函式的字首也統計過,但此時他們已不是最長,減去對應個數。
#includeusing namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int mod1=998244353;
//const ll mod2=1222827239;
const int x=2333;
const int maxn=1e5+5;
unordered_mapop;
int id(char c)
ull hx[maxn*10];
ull tx[maxn*10];
void getsufhx(char* s)
int d[maxn][105][105][4];
void init()
void insert(char *s,int v)
void init()//啊啊啊,一定要呼叫一下
void insert(char *s,int v)
^ans[0][i]
i=0∑n
ans[
0][i
]即為答案。
#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;
using namespace std;
const int maxn=100+5;
const int mod=1e5;
const int sigma_size=4;
int ch[maxn][sigma_size],val[maxn],sz;
int mp[maxn][maxn];
int idx(char c)
void init()//啊啊啊,一定要呼叫一下
void insert(char *s,int v)
}int main()
getfail();
for(int i=0;i<=sz;i++)
if(val[i])
}/*for(int i=0;i<=sz;i++)
printf("\n");
}*/martrix_pow(mp,ans,n,sz,mod);
int res=0;
for(int i=0;i<=sz;i++)//肯定從根出發啊
printf("%d\n",res);
return 0;
}
題目大意:給出乙個n*m的字元矩陣t,你的任務是找出給定的x *y的字元矩陣p出現了多少次?
藍書上一道題,利用ac自動機解決多模板匹配,同時有一些技巧,把p每一行拆出建立ac自動機,在用t的每一行來匹配,當p的第i行出現在t的第r行,起始列編號為c時,意味著cou
nt[r
−i][
j]
count[r-i][j]
count[
r−i]
[j]應該加1,cou
nt[i
][j]
count[i][j]
count[
i][j
]代表以(i,j)為左上頂點與p相同大小的矩陣與p匹配了多少行。
//please ac
#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;
typedef long long ll;
const int maxn=1000*1000+5;
const int sigma_size=26;
int ch[maxn][sigma_size],val[maxn],sz;
int f[maxn],last[maxn],nxt[1005];//字尾鏈結
int idx(char c)
void init()
void insert(char *s,int v)
}void find(char *t,int r)//在t中找模板
{ int len=strlen(t);
int j=0;
for(int i=0;i 把每次列印的串建立ac自動機,順便建立fail樹。查詢第x個字串在第y個字串**現了幾次,其實就是找到fail樹中x的單詞節點的子樹中有多少個點屬於y.維護子樹中內容,想到可以使用dfs序用樹狀陣列或線段樹維護。那麼對於查詢我們也可以用trie樹來維護y,查詢時就dfs trie樹,進入單點更新給對應節點+1,退出單點更新-1,遇到單詞節點查詢對應x節點子樹權值和,賦給對應查詢答案。
做本題時,到想到線段樹維護dfs序都比較順利,用trie維護查詢想了挺久,**敲了半天,但感覺實現起來還是有很多注意的,改的有點自閉,之後重新想一想再把**補上吧。
ac自動機 匹配最長字首 高階 AC自動機詳解
今天我們來介紹一點高階的知識 ac自動機。ac自動機是什麼呢?是不是用了這個演算法,不管什麼題目都會自動ac呢?別做夢啦 ac自動機,是aho corasick automaton的簡稱,該演算法在1975年產生於貝爾實驗室,是著名的多模匹配演算法。ac自動機是對字典樹演算法的一種延伸,是字串中運用...
ac自動機 匹配最長字首 多模匹配 AC自動機
精確的字串匹配演算法有 單模匹配演算法,比如,kmp bm演算法等 和 多模匹配演算法,比如,wu manber ac演算法等。ac演算法 aho corasick 是kmp演算法向多模式串情形的擴充套件,該演算法使用一種特殊的自動機,即ac自動機。ac自動機由一組模式串p生成,是trie的擴充套件...
AC自動機 建立nlogn個AC自動機
string set queries 題意 給你3種操作,1 加入乙個串到集合中。2 刪除集合中的某乙個串 3 查詢集合中的字串在給定的字串種出現幾次。同乙個串可重複 解法 建立多個ac自動機,用二進位制分組來處理。加入給你21個串 分為 16 4 1,再新增乙個串的時候,即21 1,22 16 4...