在字典樹上進行kmp匹配
正常建立trie樹
處理失配指標
在ac自動機中,失配指標fail和kmp的next是一樣的作用,如下圖(from superjvruo)
不難看出fail指標的構造方法:通過bfs,設這個節點上的字母為c,沿著他父親的fail走,直到走到乙個節點,他的兒子中也有字母為c的節點,我們就找到了所求的fail。
匹配模擬kmp,我們可以先在樹上走,如果失去匹配,就跳fail指標
優化進行路徑壓縮,把trie樹變成圖
#include constview codeint maxn = 1000010
;char
ss[maxn];
struct
node
};node *root = new
node;
void insert(char *s)
++p ->exist;
}void get_fail()
else
p = p ->fail;
}if (p == null) tmp -> ch[i] -> fail =root;
}q.push(tmp ->ch[i]);}}
}int ac(char *s)
}return
cnt;
}int
main()
get_fail();
scanf("%s
", ss);
printf("%d
", ac(ss));
return0;
}
不是很熟
是兩棵回文樹。其中乙個維護長度為奇數的字串,另乙個是長度為偶數的字串
直接在字串兩端進行擴充套件。每次要加入乙個點的時候,先跳最後加入的乙個節點的fail指標,直到滿足節點字元等於新加入字元。然後加入新節點,把剛剛找到的那個節點的對應邊連到新節點上, 更新節點維護的所有值
1 #include2view code3const
int maxn=555555;4
5int cnt=1;6
char
s[maxn];
7int son[maxn][26];8
intlen[maxn],fail[maxn];910
int new_node(int
length)
1115
16int get_fail(char t,int pre,int
now)
1722
23void build(char
t)24
37 last=son[cur][t[i]-'a'
];38}39
}4041int
main()
42
不是很熟+1
乙個dag,滿足從根出發走到所有結束點的所有路徑都是字串的乙個字尾
每次盡可能利用上一次的狀態得到新的狀態。我也說不明白,背的板子。。
可以解決雜湊解決不了的所有字串問題。廣義字尾自動機還可以解決其他很多問題。
1 #include2 #include3 #include4view code5 typedef long
long
ll;6
const
int maxn=1111111;7
8struct
node
9sam[maxn<<1
];13
14int cnt=1,last=1;15
int size[maxn<<1
];16
17void insert(int
ch)18
27if(!p) sam[cur].link=1;28
else
2943 sam[q].link=sam[cur].link=clone;44}
45}46 size[cur]=1
;47 last=cur;48}
4950
ll ans;
51char
s[maxn];
52int
tong[maxn];
53int topo[maxn<<1
];54
55int
main()
5674 printf("
%lld\n
",ans);
75return0;
76 }
字串 回文自動機
回文自動機學習部落格 我喜歡這個 風格 這個思想講解的更好 思路 對a b跑一次回文自動機,然後分別搜偶數長度的串,奇數長度串。code include define ll long long using namespace std const int ax 2e5 666 char a ax ch...
字串 字尾自動機
struct sam void extend int c if p 0 int q nxt p c if len p 1 len q int v siz mc nxt v nxt q len v len p 1 lnk v lnk q cnt v 0 while p 0 nxt p c q lnk ...
總結 字串 AC自動機 KMP演算法
ac自動機與kmp演算法,都是用於優化字串匹配的演算法。kmp演算法應用於單模式串的匹配。而ac自動機是應用於多模式串的匹配。但並不意味著kmp演算法可以被完全取代 儘管兩者的演算法思想本質上是一樣的 相對而言,kmp演算法比較容易一些。首先,考慮如何暴力匹配?很顯然,可以以主串的任意乙個位置開頭,...