Day 2 整理

来源:互联网 发布:手机淘宝卖家中心网址 编辑:程序博客网 时间:2024/06/08 10:37

AC自动机
KMP在Trie上的完美运用,在Trie树上构建fail指针
AC自动机的构造:
1.构造一棵Trie,作为AC自动机的搜索数据结构。
2.构造fail指针,使当前字符失配时跳转到具有最长公共前后缀的字符继续匹配。如同 KMP算法一样, AC自动机在匹配时如果当前字符匹配失败,那么利用fail指针进行跳转。由此可知如果跳转,跳转后的串的前缀,必为跳转前的模式串的后缀并且跳转的新位置的深度(匹配字符个数)一定小于跳之前的节点。所以我们可以利用 bfs在 Trie上面进行 fail指针的求解。
3.扫描主串进行匹配。

后缀数组:

#define rep(i,n) for(int i = 0;i < n; i++)using namespace std;const int size  = 200005,INF = 1<<30;int rk[size],sa[size],height[size],w[size],wa[size],res[size];void getSa (int len,int up) {    int *k = rk,*id = height,*r = res, *cnt = wa;    rep(i,up) cnt[i] = 0;    rep(i,len) cnt[k[i] = w[i]]++;    rep(i,up) cnt[i+1] += cnt[i];    for(int i = len - 1; i >= 0; i--) {        sa[--cnt[k[i]]] = i;    }    int d = 1,p = 0;    while(p < len){        for(int i = len - d; i < len; i++) id[p++] = i;        rep(i,len)  if(sa[i] >= d) id[p++] = sa[i] - d;        rep(i,len) r[i] = k[id[i]];        rep(i,up) cnt[i] = 0;        rep(i,len) cnt[r[i]]++;        rep(i,up) cnt[i+1] += cnt[i];        for(int i = len - 1; i >= 0; i--) {            sa[--cnt[r[i]]] = id[i];        }         swap(k,r);        p = 0;        k[sa[0]] = p++;        rep(i,len-1) {            if(sa[i]+d < len && sa[i+1]+d <len &&r[sa[i]] == r[sa[i+1]]&& r[sa[i]+d] == r[sa[i+1]+d])                k[sa[i+1]] = p - 1;            else k[sa[i+1]] = p++;        }        if(p >= len) return ;        d *= 2,up = p, p = 0;    }}void getHeight(int len) {    rep(i,len) rk[sa[i]] = i;    height[0] =  0;    for(int i = 0,p = 0; i < len - 1; i++) {        int j = sa[rk[i]-1];        while(i+p < len&& j+p < len&& w[i+p] == w[j+p]) {            p++;        }        height[rk[i]] = p;        p = max(0,p - 1);    }}int getSuffix(char s[]) {    int len = strlen(s),up = 0;     for(int i = 0; i < len; i++) {        w[i] = s[i];        up = max(up,w[i]);    }    w[len++] = 0;    getSa(len,up+1);    getHeight(len);    return len;}

我原来好像好写过一篇后缀数组基于sort的博客,但是就是比较慢一点(也不会差太多,常数级别)
贴一下吧:

int n,k,rank[maxn],tmp[maxn];bool compare_sa(int i,int j){    if(rank[i]!=ramk[j]) return rank[i] < rank[j];    else{        int ri = i+k <= n ? rank[i+k] : -1;        int rj = j+k <= n ? rank[j+k] : -1;        return ri < rj;    }}void construct_sa(string s,int *sa){    n = s.length();    for(int i=0;i<=n;i++){        sa[i]=i;        rank[i]= i < n ? s[i] : -1;    }    for(int k=1; k<=n;k*=2){        sort(sa,sa+n+1,compare_sa);        tmp[sa[0]]=0;        for(int i=1;i<=n;i++){            tmp[sa[i]] = tmp[sa[i-1]] + (sonpare_sa(sa[i-1],sa[i]) ? 1 : 0);        }        for(int i=0;i<=n;i++){            rank[i]=tmp[i];        }    }}
0 0