kmp演算法是乙個字串匹配演算法,最直白的用法就是在乙個長度為n的字串t中查詢另乙個長度為m字串p的匹配(總之就是用於文字中進行單個字串的匹配)。
對於這個問題,暴力演算法是很好做的,直接對於t的每個位置判斷一下當前位置作為p的結尾是否可以匹配成功,演算法複雜度是o(nm)。
kmp演算法的主要思想是:假設現在正在用p的第j個字元和t的第i個字元進行匹配,如果成功就匹配下乙個字元;如果失敗的話就跳到 以j-1個字元為結尾的字尾的 最長相同字首的結尾 後乙個位置進行匹配。為此要把p做成乙個狀態機(也就是失配函式),在上面根據情況進行轉移。
複雜分析:每一次i增加的時候伴隨著j的增加,i增加的時候為j提供了減少的空間,因此j最多會減少n次。加上預處理的時間,總時間複雜度o(n+m)。(這次一定要好好記住,之前看一次忘一次。。。)
下面給出上面問題的**(n<=1000000,m<=10000)。
1 #include2 #include3 #include4 #include5 #include6 #include7 #include8 #include9 #include10 #include11 #include12
using
namespace
std;
13const
int maxn=1000005;14
const
int maxm=10005;15
16int
n,f[maxn];
17char
p[maxm],t[maxn];
1819
void getfail(char *p)
2028}29
int find(char *t,char *p)
3038
return
re;39}40
intmain()
4147
return0;
48 }
trie是一種可以讓你歡快的在字典中查詢單詞的資料結構,所以單次查詢時間複雜度為什麼是o(1)。。。。。。
下面的**是這樣乙個問題:給出乙個長字串和一些字典中的單詞,問用這些單詞拼接出長字串的方案數mod20071027答案是多少,單詞可以重複使用。倒著插入所有字典之後dp就可以了。
1 #include2 #include3 #include4 #include5 #include6 #include7 #include8 #include9 #include10 #include11 #include12
using
namespace
std;
13const
int maxn=1000005;14
const
int maxm=105;15
const
int mo=20071027;16
17int
n,f[maxn];
18char
t[maxn],s[maxm];
19struct
trie
24void insert(char *s)
2533 now=ch[now][s[i--]-'a'
];34
}35 val[now]++;36}
37int find(int
i)38
45if(!i&&val[ch[now][t[i]-'
a']]) re=(re+1)%mo;
46return
re;47}48
}trie;
4950
void
data_in()
5157}58
void
work()
5964
intmain()
65
KMP 初級板子 待更新
複雜度 o n m 這個博主寫的蠻不錯的 1.本文中,所有的字串從0開始編號 2.為了在程式中表示方便,在接下來的說明中,next i 0表示最長相同字首字尾長度為 即真實的最長相同字首字尾 next i 1。重要的內容要放大 includeusing namespace std const int...
KMP 初級板子 待更新
複雜度 o n m 這個博主寫的蠻不錯的 1.本文中,所有的字串從0開始編號 2.為了在程式中表示方便,在接下來的說明中,next i 0表示最長相同字首字尾長度為 即真實的最長相同字首字尾 next i 1。重要的內容要放大 includeusing namespace std const int...
板子 KM(n3板子)
include using namespace std define ll long long 演算法使用 w maxn maxn 陣列表示圖的鄰接矩陣 pop表示二分圖的左右兩邊的點的數量 點從0到n 1 const int maxn 50 const int inf 0x3f3f3f3f int...