有一些板,我以前写了,但是没有存下来,这样就不移动。因此要写到博客上。
KMP
int t1 = 0, t2 = nxt[0] = -1;
while(t1 < tn) if(t2 == -1 || t[t1] == t[t2]) {
t1++; t2++;
if(t[t1] == t[t2]) nxt[t1] = nxt[t2];
else nxt[t1] = t2;
}else t2 = nxt[t2];
int k = 0;
for(int i = 0; i < sn; i++) {
while(k && s[i] != t[k]) k = nxt[k];
if(s[i] == t[k]) k++;
if(k == tn) printf("Find at %d\n", i);
}
AC AUTOMATON
Updated for 3 times on 2018.3.9
struct node {
int c;
node* p, *ch[26];
};
inline node* newnode() {
node* ret = new node;
ret->c = 0;
ret->p = NULL;
for(int i = 0; i < 26; i++) ret->ch[i] = NULL;
return ret;
}
node* q[maxn];
int head, tail;
char s[1000050];
char t[100];
node* root;
void insert(char* t) {
node* o = root;
for(int i = 0; t[i]; i++) {
int c = t[i] - 'a';
if(!o->ch[c]) o->ch[c] = newnode();
o = o->ch[c];
}
o->c++;
}
void buildfail() {
head = tail = 0;
q[tail++] = root;
while(head < tail) {
node* f = q[head++], *p = NULL;
for(int i = 0; i < 26; i++) if(f->ch[i]) {
q[tail++] = f->ch[i];
if(f == root) {
f->ch[i]->p = root;
continue;
}
p = f->p;
while(p) {
if(p->ch[i]) {
f->ch[i]->p = p->ch[i];
break;
}
p = p->p;
}
if(!p) f->ch[i]->p = root;
}
}
}
int query() {
node* o = root;
for(int i = 0; s[i]; i++) {
int c = s[i] - 'a';
while(o != root && !o->ch[c]) o = o->p;
o = o->ch[c];
if(!o) o = root;
node* cur = o;
while(cur != root) {
if(cur->c >= 0) {
// what do you want to do
//cur->c = -1;
}//else break;
cur = cur->p;
}
}
}
Manacher
Updated on 2018.3.9
int n = strlen(s);
for(int i = 0; i < n; i++) {
t[i*2] = '$';
t[i*2+1] = s[i];
}
t[n*2] = '$';
rgt = -1;
int ans = 0;
n = n*2 + 1;
for(int i = 0; i < n; i++) {
if(rgt >= i) pal[i] = min(pal[2*ct-i], rgt-i);
while(i-pal[i]-1 >= 0 && i+pal[i]+1 < n && t[i-pal[i]-1] == t[i+pal[i]+1]) {
pal[i]++;
}
if(i+pal[i] > rgt) {
rgt = i + pal[i];
ct = i;
}
ans = max(ans, pal[i]);
}
SA
char s[maxn];
int sa[maxn], t[maxn], t2[maxn], b[maxn], n;
void buildsa() {
int i, *x = t, *y = t2;
for(int i = 0; i < m; i++) b[i] = 0;
for(int i = 0; i < n; i++) b[x[i]=s[i]]++;
for(int i = 1; i < m; i++) b[i] = b[i-1];
for(int i = n-1; i >= 0; i--) sa[--b[x[i]]] = i;
for(int k = 1; k <= n; k <<= 1) {
int p = 0;
for(int i = n-k; i < n; i++) y[p++] = i;
for(int i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
for(int i = 0; i < m; i++) b[i] = 0;
for(int i = 0; i < n; i++) b[x[y[i]]]++;
for(int i = 0; i < m; i++) b[i] += b[i-1];
for(int i = n-1; i >= 0; i--) sa[--b[x[y[i]]]] = y[i];
swap(x, y);
p = 1; x[sa[0]] = 0;
for(int i = 1; i < n; i++) x[sa[i]] = y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]] ? p-1 : p++;
if(p >= n) break;
m = p;
}
}
void geth() {
int k = 0;
for(int i = 0; i < n; i++) rk[sa[i]] = i;
for(int i = 0; i < n; i++) {
if(k) k--;
int j = sa[rk[i]-1];
while(s[i+k] == s[j+k]) k++;
h[rk[i]] = k;
}
}
使用SA可以把LCP问题转化为RMQ问题。
对于多模式匹配,使用
H
e
i
g
h
t
Height
Height数组时间复杂度是
O
(
m
+
log
n
)
O(m+\log n)
O(m+logn)。
更多参见:
哈希
哈希数组可以用线性时间预处理,然后常熟时间得到任意一个字串的哈希值。
基于哈希值的字符串算法真的很不错。——lrj
明天:回文自动机
后缀自动机
Updated on 2018.3.9
//forced by dxymaster
void insert(int x) {
node* o = newnode(), *p = last;
last = o;
o->len = p->len + 1;
for(; p && !p->ch[x]; p = p->f) p->ch[x] = o;
if(!p) {
o->f = root;
return;
}
node* q = p->ch[x];
if(q->len + 1 == p->len) o->f = q;
else{
node* q2 = newnode();
q2->len = p->len + 1;
for(char i = 0; i < 26; i++) q2->ch[i] = q->ch[i];
o->f = q->f = q2; q2->f = p;
for(; p && p->ch[x] == q; p = p->f) p->ch[x] = q2;
}
}
Upd on 20180723
上面的是错的
struct node {
node* ch[26], *f;
int len, siz;
};
node* _nd = (node*)malloc(1024*1024*450); int noden;
node* root, *last;
inline node* newnode(node* fa) {
node* ret = _nd+(noden++);
if(fa) ret->len = fa->len + 1; else ret->len = 0; ret->siz = 0;
return ret;
}
inline void extend(int x) {
node* o = newnode(last), *p = last; o->siz = 1;
last = o;
for(; p && !p->ch[x]; p = p->f) p->ch[x] = o;
if(!p) {o->f = root; return;}
node* q = p->ch[x];
if(q->len == p->len + 1) o->f = q;
else{
node* nq = newnode(p);
memcpy(nq->ch, q->ch, sizeof(q->ch));
nq->f = q->f; q->f = o->f = nq;
for(; p && p->ch[x] == q; p = p->f) p->ch[x] = nq;
}
}
int topo_b[maxn], topo[maxn];
inline void get_topo() {
for(int i = 0; i < noden; i++) topo_b[(_nd+i)->len]++;
for(int i = 1; i < noden; i++) topo_b[i] += topo_b[i-1];
for(int i = 0; i < noden; i++) topo[--topo_b[(_nd+i)->len]] = i;
}
最小表示法 upd on 2018.12.28
先将字符串复制一遍。
inline int minr() {
int i = 0, j = 1;
while(i < n && j < n) { // n是原串长度
int k = 0;
while(s[i+k] == s[j+k] && k < n) k++;
if(k == n) return min(i, j);
if(s[i+k] > s[j+k]) i = max(i+k-1, j+1);
else j = max(j+k-1, i+1);
}
}