0
点赞
收藏
分享

微信扫一扫

「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)

蚁族的乐土 2022-07-12 阅读 26

「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_子树 传送门​​

  • 开题,咦?怎么做过,咦?怎么不会了
  • 题解:挺好的一道题,第一遍记不清多久写的了不过肯定是抄的。
    考虑暴力,枚举匹配位置,尽量匹配一个前缀和后缀,如果中间空缺的位置长度「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_后缀_02就有 1 的贡献
    我们对询问串极其反串建「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_后缀_03自动机,考虑对于正串一个结点,假设它代表的串的长度为「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_子树_04,钦定「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_i++_05与这个正串的前「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_子树_04位完美匹配,那么现在需要保证后「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_子树_07位要完美匹配。设当前节点为「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_子树_08,反过来的「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_后缀_03自动机的「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_子树_07代表的节点为「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_i++_11,那么需要合法的匹配位置就是正着的第「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_子树_12位出现在「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_子树_08「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_后缀_14子树中,反过来的第「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_子树_15位出现在「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_i++_11的子树中,因为要保证「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_子树_07这个后缀是「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_子树_15这个后缀的前缀。
  • 所以问题被我们简化了,对于正着的第「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_子树_12位走到的节点,我们把反过来的「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_后缀_03自动机的「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_子树_15代表的节点点亮,如果我们将所有「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_子树_08子树中的对应的节点点亮后,「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_i++_11中点亮的个数就是匹配次数,「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_子树_24序 +「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_子树_25
  • 但是有个小问题,令一个位置匹配尽量匹配前缀后缀后中间的长度为空缺长度「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_后缀_26,那么一个「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_i++_27会被算「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_后缀_28次,我们想让其只算一次,所以我们求出「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_子树_29的答案容斥掉。
    但这样又会有一个头疼的问题,令前缀匹配长度为「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_子树_04,那么次数实际上是「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_后缀_31,将「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_i++_32置为「HAOI2017」字符串 (AC自动机)(BIT)(dfs序)_子树_29算可能减掉相同的量,这里需要特殊处理。
#include<bits/stdc++.h>
#define cs const
using namespace std;
cs int N = 4e5 + 50;
int k, n, m; char S[N];
int len[N], ch[N][95], fail[N], as[N], nd;
vector<int> G[N]; int in[N], out[N], sgn;
struct data{
int c, u, v, ur, vr;
data(int _c = 0, int _u = 0, int _v = 0, int _ur = 0, int _vr = 0){
c = _c; u = _u; v = _v; ur = _ur; vr = _vr;
}
};
vector<data> v[N];
vector<int> p[N],q[N];
void ins(int w, char *S){
int len = strlen(S+1), now = 0;
for(int i = 1; i <= len; i++){
int c = S[i] - 33; if(!ch[now][c]) ch[now][c] = ++nd;
now = ch[now][c];
}
static int ps[N]; ps[len+1] = 0; now = 0;
for(int i = len; i >= 1; i--){
int c = S[i] - 33; if(!ch[now][c]) ch[now][c] = ++nd;
now = ch[now][c]; ps[i] = now;
}
for(int i = 0, now = 0; i + k <= len; i++){
data nx(w, ps[i+k+1], i ? ps[i+k] : -1);
v[now].push_back(nx); now = ch[now][S[i+1]-33];
}
}
void build(){
queue<int> q;
for(int i = 0; i <= 94; i++) if(ch[0][i]) q.push(ch[0][i]);
while(!q.empty()){
int x = q.front(); q.pop();
for(int i = 0; i <= 94; i++)
if(ch[x][i]) fail[ch[x][i]] = ch[fail[x]][i], q.push(ch[x][i]);
else ch[x][i] = ch[fail[x]][i];
}
for(int i = 1; i <= nd; i++) G[fail[i]].push_back(i);
}
void pre_dfs(int u){ in[u] = ++sgn; for(int v : G[u]) pre_dfs(v); out[u] = sgn; }
struct BIT{
int c[N];
void add(int x){ for(;x<=sgn;x+=x&-x) ++c[x]; }
int ask(int x){ int as=0; for(;x;x-=x&-x) as+=c[x]; return as; }
int qry(int l, int r){ return ask(r)-ask(l-1); }
}T[2];
void work(int u){
for(auto &t : v[u]){
t.ur = T[0].qry(in[t.u],out[t.u]);
if(~t.v) t.vr = T[1].qry(in[t.v],out[t.v]);
}
for(auto t : p[u]) T[0].add(in[t]);
for(auto t : q[u]) T[1].add(in[t]);
for(int v : G[u]) work(v);
for(auto t : v[u]){
as[t.c] += T[0].qry(in[t.u],out[t.u]) - t.ur;
if(~t.v) as[t.c] -= T[1].qry(in[t.v],out[t.v]) - t.vr;
}
}
int main(){
scanf("%d%s%d",&k,S+1,&m); n = strlen(S+1);
for(int i = 1; i <= m; i++){
static char s[N];
scanf("%s",s+1); int len = strlen(s+1);
if(len <= k){ as[i] = max(0, n-len+1); continue; } ins(i,s);
} build();
static int pos[N];
for(int i = n, now = 0; i >= 1; i--) pos[i] = now = ch[now][S[i]-33];
for(int i = 0, now = 0; i + k <= n; i++){
p[now].push_back(pos[i+k+1]);
q[now].push_back(pos[i+k]); now = ch[now][S[i+1]-33];
} pre_dfs(0); work(0);
for(int i = 1; i <= m; i++) cout << as[i] << '\n';
}


举报

相关推荐

0 条评论