社区讨论
求助(悬赏关注1,有注释)
P2414[NOI2011] 阿狸的打字机参与者 2已保存回复 3
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @lo11jeuh
- 此快照首次捕获于
- 2023/10/22 13:41 2 年前
- 此快照最后确认于
- 2023/11/02 13:11 2 年前
先说一下问题吧,问题在于有一些询问并没有处理到,但是不知道为什么会有问题。
感谢
CPP#include<bits/stdc++.h>
using namespace std;
int tree[100005][26];
int from[100005];
int fail[100005];
bool tail[100005];
int idtail[100005];
vector<int>mp[100005];
int ans[100005];
int ids=0;
int cnt=0;
/*
把sj的每个前缀的点标记一下,然后fail树上以si为根的子树求和
然后将j从小到大排序般打标记,由于输入比较特殊的原因,j从小到大排序后新的字符串一定可以通过上一次搞到
至于树上求子树和,可以dfn序列然后树状数组?大概就是单修区查?
*/
void add(string s){
int sz=s.size();
int p=0;
for(int i=0;i<sz;i++){
if(s[i]>='a'&&s[i]<='z'){
int c=s[i]-'a';
if(!tree[p][c]){
cnt++;
tree[p][c]=cnt;
from[cnt]=p;
}
p=tree[p][c];
}
else if(s[i]=='P'){
tail[p]=1;
ids++;
idtail[ids]=p;//表示第i个出现的字符串的尾巴的位值
}
else{
p=from[p];
}
}
}
void build(){
queue<int>q;
for(int i=0;i<26;i++){
if(tree[0][i]){
q.push(tree[0][i]);
}
}
while(q.size()){
int u=q.front();
q.pop();
for(int i=0;i<26;i++){
if(tree[u][i]){
q.push(tree[u][i]);
fail[tree[u][i]]=tree[fail[u]][i];
}
else{
tree[u][i]=tree[fail[u]][i];
}
}
}
for(int i=1;i<=cnt;i++){
int ffrom=fail[i];
mp[ffrom].push_back(i);
}
}
struct ak{
int x;
int y;
int id;
}ask[100005];
bool cmp(ak x,ak y){
return x.y<y.y;
}
int tk=0;
int dfn[100005];
int sz[100005];
void dfs(int x,int fa){
dfn[x]=++tk;
sz[dfn[x]]=1;
for(int i=0;i<mp[x].size();i++){
int to=mp[x][i];
if(to==fa){
continue;
}
dfs(to,x);
sz[dfn[x]]+=sz[dfn[to]];
}
}
int tr[100005];
int lowbit(int x){
return x&(-x);
}
void ad(int pos,int val){
for(int i=pos;i<=cnt;i+=lowbit(i)){
tr[i]+=val;
}
}
int query(int pos){
int ret=0;
for(int i=pos;i>=1;i-=lowbit(i)){
ret+=tr[i];
}
return ret;
}
int onask=1;
void getans(string s){//我再走一遍s来模拟
int siz=s.size();
int p=0;
for(int i=0;i<siz;i++){
if(s[i]>='a'&&s[i]<='z'){//不管怎么样,现在肯定再走一个前缀
int c=s[i]-'a';
p=tree[p][c];
int df=dfn[p];
ad(df,1);//在dfn上加上这个点
}
else if(s[i]=='P'){//到达一个实串
while(p==idtail[ask[onask].y]){//现在正是在询问上 ,且在y串上
int xx=dfn[ask[onask].x];
int r1=query(xx+sz[xx]-1);
int r2=query(xx-1);
ans[ask[onask].id]=r1-r2;
onask++;
}
}
else{//我正在回退
int df=dfn[p];
ad(df,-1);//在dfn上加上这个点
p=from[p];
}
}
}
int main(){
ios::sync_with_stdio(false);
string s;
cin >> s;
add(s);
build();
dfs(0,0);
int m;
cin >> m;
for(int i=1;i<=m;i++){
cin >> ask[i].x >> ask[i].y;
ask[i].id=i;
}
sort(ask+1,ask+1+m,cmp);
getans(s);//我再走一遍s来模拟
for(int i=1;i<=m;i++){
cout<<ans[i]<<endl;
}
}
回复
共 3 条回复,欢迎继续交流。
正在加载回复...