调了下午到晚上
从0->40->70->100
心力交瘁
40分做法:
直接在fail树上暴力跳,修改节点值,树状数组查询时间复杂度n^2log
70分做法:
接近正解,离线询问,在对应的位置打标记,dfs的时候可以遍历到这个点的时候,对这个点所有的询问都可以同时处理出来
100分做法:
读入的时侯可以优化一下,对于原来建过的Trie不用再建,优化一下非常快
代码
#include<bits/stdc++.h>
#include<vector>
using namespace std;
const int maxn=1e5+5;
char s1[maxn];
char ch[maxn];
struct edge {
int tov,nxt;
}e[maxn<<1];
int ans[maxn];
struct qu {
int x,y,id;
}q[maxn];
vector<qu> ex[maxn<<1];
bool vis[maxn];
int h[maxn<<1];
int last[maxn];
int val[maxn];
int dep[maxn];
int root=0;
struct Node {
int fail;
int nxt[26];
int jz[26];
}ac[maxn<<1];
int in[maxn],out[maxn];
int fa[maxn];
int lastpos,tot,cnt,m,idx,l,r,da;
void add(int u,int v) {
tot++;
e[tot].tov=v;
e[tot].nxt=h[u];
h[u]=tot;
}
char s[maxn];
void insert(int num) {
for (int i=l+1;i<=r;i++) {
int id=s[i]-'a';
if (!ac[da].nxt[id]) {
ac[da].nxt[id]=++cnt;
}
fa[ac[da].nxt[id]]=da;
da=ac[da].nxt[id];
}
last[num]=da;
}
void getroot() {
root=0;
dep[root]=0;
ac[root].fail=root;
for (int i=0;i<=25;i++) {
ac[root].nxt[i]=root;
}
}
int que[maxn<<1];
void getfail() {
int head=0,tail=0;
int now=root;
for (int i=0;i<=25;i++) {
if (ac[now].nxt[i]) {
que[tail++]=ac[now].nxt[i];
add(root,ac[now].nxt[i]);
ac[ac[now].nxt[i]].fail=root;
}
}
while (head<tail) {
int u=que[head++];
for (int i=0;i<=25;i++) {
int son=ac[u].nxt[i];
int fafail=ac[u].fail;
if (son) {
que[tail++]=son;
ac[son].fail=ac[fafail].nxt[i];
add(ac[son].fail,son);
} else {
ac[u].nxt[i]=ac[fafail].nxt[i];
}
}
}
}
int lowbit(int x) {
return x&-x;
}
void modify(int pos,int delta) {
for (int i=pos;i<=idx;i+=lowbit(i)) {
val[i]+=delta;
}
}
int query(int pos) {
int rt=0;
for (int i=pos;i>=1;i-=lowbit(i)) {
rt+=val[i];
}
return rt;
}
void dfs(int u) {
vis[u]=1;
in[u]=++idx;
for (int i=h[u];i;i=e[i].nxt) {
int v=e[i].tov;
if (vis[v]) continue;
dfs(v);
}
out[u]=idx;
}
void dfs1(int u) {
vis[u]=1;
modify(in[u],1);
if (ex[u].size()) {
for (int i=0;i<ex[u].size();i++) {
int tmp=ex[u][i].x;
int tmp1=query(out[last[tmp]]);
int tmp2=query(in[last[tmp]]-1);
ans[ex[u][i].id]=tmp1-tmp2;
}
}
for (int i=0;i<=25;i++) {
int v=ac[u].jz[i];
if(!v) continue;
if (vis[v]) continue;
dfs1(v);
}
modify(in[u],-1);
}
int main() {
scanf("%s",s1);
getroot();
int len=strlen(s1);
int pos=0;
int tim=0;
for (int i=0;i<=len-1;i++) {
if (s1[i]>='a'&&s1[i]<='z') {
r++;
s[r]=s1[i];
} else if (s1[i]=='P') {
insert(++tim);
l=r;
} else {
if(r==l) l--;
r--;
da=fa[da];
}
}
for(int o=0;o<=cnt;o++)
for(int i=0;i<26;i++)
ac[o].jz[i]=ac[o].nxt[i];
getfail();
dfs(root);
scanf("%d",&m);
for (int i=1;i<=m;i++) {
scanf("%d%d",&q[i].x,&q[i].y);
q[i].id=i;
ex[last[q[i].y]].push_back(q[i]);
}
memset(vis,0,sizeof(vis));
dfs1(root);
for (int i=1;i<=m;i++) {
printf("%d\n",ans[i]);
}
return 0;
}