P3808 AC 自动机(简单版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef long double ldb;
typedef pair<int, int> pii;
typedef pair<ll, ll> PII;
#define pb emplace_back
//#define int ll
#define all(a) a.begin(),a.end()
#define x first
#define y second
#define ps push_back
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
void solve();
const int N = 1e6 + 10;
signed main() {
IOS;
solve();
return 0;
}
ll ch[N][26],idx;//ch 存储树边和转移边
ll ne[N];//ne 存储回跳边
ll cnt[N];//单词个数cnt
void c_insert(string s)//*****************错误*2
{
ll p = 0;
for(auto it : s)
{
ll j = it - 'a';
//************这里写错了:ch[p][j] = ++ idx;
if(!ch[p][j]) ch[p][j] = ++ idx;
//************这里写错了:p = idx;
p = ch[p][j];
}
cnt[p] ++;
}
void c_bulid()
{
queue<ll> q;
for(int i = 0; i < 26; ++ i)
if(ch[0][i]) q.push(ch[0][i]);
while(!q.empty())
{
ll u = q.front();//父节点
q.pop();
for(int i = 0; i < 26; ++ i)
{
ll v = ch[u][i];
if(v)//有儿子
ne[v] = ch[ne[u]][i],q.push(v);
else//自建转移边
ch[u][i] = ch[ne[u]][i];
}
}
}
ll c_query(string s)
{
ll ans = 0;ll p = 0;
// for(auto it : s)
// {
// ll p = ch[p][it - 'a'];
// for(int j = p; j && ~cnt[j]; j = ne[j])
// {
// ans += cnt[j];cnt[j] = -1;
// }
//
// }
for(int k=0,i=0; k < s.size(); ++ k)
{
i = ch[i][s[k] - 'a'];
for(int j = i; j && ~cnt[j]; j = ne[j])
{
ans += cnt[j];cnt[j] = -1;
}
}
return ans;
}
void solve() {
ll n;
cin >> n;
string s;
for(int i = 1; i <= n; ++ i)
{cin >> s; c_insert(s);}
cin >> s;
c_bulid();
cout << c_query(s);
}
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef long double ldb;
typedef pair<int, int> pii;
typedef pair<ll, ll> PII;
#define pb emplace_back
//#define int ll
#define all(a) a.begin(),a.end()
#define x first
#define y second
#define ps push_back
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
void solve();
const int N = 1e6 + 10;
signed main() {
IOS;
solve();
return 0;
}
ll ch[N][26],idx;//ch 存储树边和转移边
ll ne[N];//ne 存储回跳边
ll cnt[N];//单词个数cnt
void c_insert(string s)//*****************错误*2
{
ll p = 0;
for(auto it : s)
{
ll j = it - 'a';
//************这里写错了:ch[p][j] = ++ idx;
if(!ch[p][j]) ch[p][j] = ++ idx;
//************这里写错了:p = idx;
p = ch[p][j];
}
cnt[p] ++;
}
void c_bulid()
{
queue<ll> q;
for(int i = 0; i < 26; ++ i)
if(ch[0][i]) q.push(ch[0][i]);
while(!q.empty())
{
ll u = q.front();//父节点
q.pop();
for(int i = 0; i < 26; ++ i)
{
ll v = ch[u][i];
if(v)//有儿子
ne[v] = ch[ne[u]][i],q.push(v);
else//自建转移边
ch[u][i] = ch[ne[u]][i];
}
}
}
ll c_query(string s)
{
ll ans = 0;ll p = 0;
for(auto it : s)
{
p = ch[p][it - 'a'];//tmd,我服了,写成这个了:ll p = ch[p][it - 'a'];
for(int j = p; j && ~cnt[j]; j = ne[j])//匹配
{
ans += cnt[j];cnt[j] = -1;//更新ans ,设为-1防止再次计数
}
}
// for(int k=0,i=0; k < s.size(); ++ k)
// {
// i = ch[i][s[k] - 'a'];
// for(int j = i; j && ~cnt[j]; j = ne[j])
// {
// ans += cnt[j];cnt[j] = -1;
// }
// }
return ans;
}
void solve() {
ll n;
cin >> n;
string s;
for(int i = 1; i <= n; ++ i)
{cin >> s; c_insert(s);}
cin >> s;
c_bulid();
cout << c_query(s);
}