字符串相关模板

包含 KMP Trie AC自动机 dp/矩阵优化AC自动机

KMP:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

char a[1000050],b[1000050];
int nxt[1000050];

int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s %s",a + 1,b + 1);
int len = strlen(a + 1);
memset(nxt,0,sizeof(nxt));
for(int i = 2;i <= len; ++ i)
{
int lst = nxt[i - 1];
while(a[lst + 1] != a[i] && lst) lst = nxt[lst];
if(a[lst + 1] == a[i]) lst ++;
nxt[i] = lst;
}
int cur = 0;
int ans = 0;
int len2 = strlen(b + 1);
for(int i = 1;i <= len2; ++ i)
{
while(b[i] != a[cur + 1] && cur)
cur = nxt[cur];
if(a[cur + 1] == b[i]) cur ++;
if(cur == len) ans ++;
}
cout<<ans<<endl;
}
}

Trie树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
int son[5000050][10];
int val[5000050];
struct Trie
{
int cnt;
void init()
{
memset(son[0],0,sizeof(son[0]));
val[0] = 0;
cnt = 0;
}
void init_pos(int pos)
{
memset(son[pos],0,sizeof(son[pos]));
val[pos] = 0;
}
bool insert(char *s)
{
int cur = 0;
int len = strlen(s + 1);
int u;
for(int i = 1;i <= len; ++ i)
{
int u = son[cur][s[i] - '0'];
if(u == 0)
{
u = ++cnt;
init_pos(u);
son[cur][s[i] - '0'] = cnt;
cur = u;
}
else
{
if(val[u]) return false;
cur = u;
}
}
val[cur] ++;
return true;
}
bool work(int rt)
{
bool yn;
if(val[rt]) yn = true;
else yn = false;
for(int i = 0;i <= 9; ++ i)
{
int v = son[rt][i];
if(v != 0)
{
if(yn) return false;
else if(!work(v)) return false;
}
}
return true;
}
}Tr;

AC自动机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
int son[3000050][26],val[3000050];
int cnt;
int fail[3000050];
int ans;
bool vis[3000050];

struct Trie_AC
{
int get_id(char c)
{
return c - 'a';
}
void init(int pos)
{
memset(son[pos],0,sizeof(son[pos]));
val[pos] = 0;
}
void insert(char *c,int num)
{
int len = strlen(c);
int u = 0;
for(int i = 0;i < len; ++ i)
{
int v = get_id(c[i]);
int tmp = u;
u = son[u][v];
if(u == 0)
{
init(++cnt);
son[tmp][v] = cnt;
u = cnt;
}
}
val[u]++;
}
void build()
{
queue<int> q;
fail[0] = 0;
for(int i = 0;i < 26; ++ i)
if(son[0][i])
{
q.push(son[0][i]);
fail[son[0][i]] = 0;
}
while(!q.empty())
{
int u = q.front();
q.pop();
for(int i = 0;i < 26; ++ i)
{
int f = fail[u];
if(!son[u][i]) continue;
while(f && !son[f][i]) f = fail[f];
fail[son[u][i]] = son[f][i];
//lst[son[u][i]] = val[fail[son[u][i]]] ? fail[son[u][i]] : lst[fail[son[u][i]]];
q.push(son[u][i]);
}
}
}
void query(char *c)
{
int len = strlen(c);
int cur = 0;
for(int i = 0;i < len; ++ i)
{
int v = get_id(c[i]);
while(cur && !son[cur][v])
cur = fail[cur];
cur = son[cur][v];
int tmp = cur;
while(tmp)
{
ans += val[tmp];
val[tmp] = 0;
tmp = fail[tmp];
}
}
}
}Trie;
带dp的AC自动机
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
int son[2500][2];
int lst[205],fail[250];
int val[205];
int cnt;
int dp[101][101][202][4];
int n,m;
const int mod = 1000000007;

struct Trie
{
int get_id(char c)
{
return c == 'R';
}
void init(int pos)
{
son[pos][0] = son[pos][1] = 0;
val[pos] = 0;
}
void insert(char* c,int id)
{
int len = strlen(c);
int u = 0;
for(int i = 0;i < len; ++ i)
{
int v = son[u][get_id(c[i])];
if(!v)
{
son[u][get_id(c[i])] = ++cnt;
init(cnt);
u = cnt;
}
else
u = v;
}
val[u] |= id;
}
void Build()
{
queue <int> q;
lst[0] = fail[0] = 0;
for(int i = 0;i <= 1; ++ i)
{
int v = son[0][i];
if(v)
{
lst[v] = fail[v] = 0;
q.push(v);
}
}
while(!q.empty())
{
int u = q.front();q.pop();
val[u] |= val[lst[u]];
for(int i = 0;i < 2; ++ i)
{
int v = son[u][i];
if(!v)
{
son[u][i] = son[fail[u]][i];
continue;
}
int f = fail[u];
while(f && !son[f][i]) f = fail[f];
fail[v] = son[f][i];
lst[v] = val[fail[v]] ? fail[v] : lst[fail[v]];
q.push(v);
}
}
}
void Do_DP()
{
for(int i = 0;i <= n; ++ i)
for(int j = 0;j <= m; ++ j)
for(int k = 0;k <= cnt; ++ k)
for(int l = 0;l < 4; ++ l)
dp[i][j][k][l] = 0;
dp[0][0][0][0] = 1;
for(int i = 0;i <= n; ++ i)
for(int j = 0;j <= m; ++ j)
for(int k = 0;k <= cnt; ++ k)
for(int l = 0;l < 4; ++ l)
{
if(dp[i][j][k][l] == 0) continue;
if(i < n)
dp[i + 1][j][son[k][1]][l | val[son[k][1]]] += dp[i][j][k][l],dp[i + 1][j][son[k][1]][l | val[son[k][1]]] %= mod;
if(j < m)
dp[i][j + 1][son[k][0]][l | val[son[k][0]]] += dp[i][j][k][l],dp[i][j + 1][son[k][0]][l | val[son[k][0]]] %= mod;
}
long long qsum = 0;
for(int i = 0;i <= cnt; ++ i)
qsum += dp[n][m][i][3],qsum %= mod;
printf("%lld\n",qsum);
}
}Trie;
带矩阵优化的AC自动机
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
long long son[2500][26];
long long lst[205],fail[250];
long long val[205];
long long cnt;
long long n,m;
const long long mod = 1000000007;

struct Matrix
{
unsigned long long sum[55][55];
long long sz;
void init(long long _sz)
{
sz = _sz;
for(long long i = 0;i <= sz; ++ i)
for(long long j = 0;j <= sz; ++ j)
sum[i][j] = 0;
}
Matrix operator * (const Matrix& a)
{
Matrix c;
c.init(a.sz);
long long lim = c.sz;
for(long long i = 0;i <= sz; ++ i)
for(long long j = 0;j <= sz; ++ j)
for(long long k = 0;k <= sz; ++ k)
c.sum[i][j] += a.sum[k][j] * sum[i][k];
return c;
}
};

Matrix qpow(Matrix A,long long tms)
{
if(tms == 1) return A;
else if(tms == 0)
{
Matrix E;
E.init(A.sz);
for(int i = 0;i <= A.sz; ++ i)
E.sum[i][i] = 1;
return E;
}
Matrix tmp = A;
tms -= 1;
while(tms)
{
if(tms & 1) tmp = tmp * A;
A = A * A;
tms >>= 1;
}
return tmp;
}

unsigned long long qpow(unsigned long long a,long long tms)
{
unsigned long long tmp = 1;
while(tms)
{
if(tms & 1) tmp *= a;
a *= a;
tms >>= 1;
}
return tmp;
}

struct Trie
{
long long get_id(char c)
{
return c - 'a';
}
void init(long long pos)
{
memset(son[pos],0,sizeof(son[pos]));
val[pos] = 0;
}
void insert(char* c,long long id)
{
long long len = strlen(c);
long long u = 0;
for(long long i = 0;i < len; ++ i)
{
long long v = son[u][get_id(c[i])];
if(!v)
{
son[u][get_id(c[i])] = ++cnt;
init(cnt);
u = cnt;
}
else
u = v;
}
val[u] |= id;
}
void Build()
{
queue <long long> q;
lst[0] = fail[0] = 0;
for(long long i = 0;i <= 25; ++ i)
{
long long v = son[0][i];
if(v)
{
lst[v] = fail[v] = 0;
q.push(v);
}
}
while(!q.empty())
{
long long u = q.front();q.pop();
val[u] |= val[lst[u]];
for(long long i = 0;i < 26; ++ i)
{
long long v = son[u][i];
if(!v)
{
son[u][i] = son[fail[u]][i];
continue;
}
long long f = fail[u];
while(f && !son[f][i]) f = fail[f];
fail[v] = son[f][i];
lst[v] = val[fail[v]] ? fail[v] : lst[fail[v]];
q.push(v);
}
}
}
void get_mat(Matrix& mat)
{
for(long long i = 0;i <= cnt; ++ i)
{
if(val[i]) continue;
for(long long j = 0;j < 26; ++ j)
{
long long k = son[i][j];
if(val[k]) continue;
mat.sum[i][k] ++;
}
}
for(long long i = 0;i <= cnt + 1; ++ i)
mat.sum[i][cnt] = 1;
}
}Trie;