bzoj2555 SubString

本文介绍了一种利用后缀自动机和LCT(链剖树)的数据结构来解决动态字符串问题的方法。该方法可以高效地处理字符串的添加、删除及查询操作,特别适用于维护动态变化的字符串集合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

后缀自动机+LCT维护parent树

其实就是要求一个动态添加的right集合大小,每次添加改变的只有last以及他的parent链上的点,我们还要维护动态删边加边,于是LCT就是最好的选择。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <cmath>
  6 #define N 1205000
  7 using namespace std;
  8 char s[N<<3],opt[10];
  9 int n,m,mask;
 10 struct Node {
 11     Node *ch[2],*fa;
 12     int id,val,lazy;
 13     void update(int x){val+=x;lazy+=x;}
 14     void pushdown();
 15     Node(){};
 16 }*null=new Node(),tree[N];
 17 void Node :: pushdown(){
 18     if(lazy){
 19         if(ch[0]!=null)ch[0]->update(lazy);
 20         if(ch[1]!=null)ch[1]->update(lazy);
 21         lazy=0;
 22     }
 23 }
 24 void init(){
 25     null->ch[0]=null->ch[1]=null->fa=null;
 26     null->id=null->val=null->lazy=0;
 27     for(int i=1;i<N;i++){
 28         tree[i].ch[0]=tree[i].ch[1]=tree[i].fa=null;
 29         tree[i].lazy=tree[i].val=0;tree[i].id=i;
 30     }
 31 }
 32 void rotate(Node *x){
 33     Node *y=x->fa,*z=y->fa;
 34     int w=y->ch[1]==x;
 35     x->ch[w^1]->fa=y;y->ch[w]=x->ch[w^1];
 36     y->fa=x;x->ch[w^1]=y;
 37     if(z->ch[0]==y)z->ch[0]=x;
 38     if(z->ch[1]==y)z->ch[1]=x;
 39     x->fa=z;
 40 }
 41 bool isroot(Node *x){
 42     return x->fa->ch[0]!=x&&x->fa->ch[1]!=x;
 43 }
 44 int get(Node *x){
 45     if(x->fa->ch[0]==x)return 0;
 46     if(x->fa->ch[1]==x)return 1;
 47     return -1;
 48 }
 49 void pushdown(Node *x){
 50     if(!isroot(x))
 51         pushdown(x->fa);
 52     x->pushdown();
 53 }
 54 void splay(Node *x){
 55     Node *y;
 56     pushdown(x);
 57     while(!isroot(x)){
 58         y=x->fa;
 59         if(!isroot(y)){
 60             if(get(y)==get(x))rotate(y);
 61             else rotate(x);
 62         }rotate(x);
 63     }
 64 }
 65 void access(Node *x){
 66     Node *y=null;
 67     while(x!=null){
 68         splay(x);
 69         x->ch[1]=y;
 70         y=x;x=x->fa;
 71     }
 72 }
 73 void cut(Node *x,Node *y){
 74     access(y);splay(y);
 75     y->ch[0]=x->fa=null;
 76 }
 77 void link(Node *x,Node *y){
 78     access(y);splay(y);
 79     x->fa=y;
 80 }
 81 void update(Node *x){
 82     access(x);
 83     splay(x);
 84     x->update(1);
 85 }
 86 void query(Node *x){
 87     access(x);
 88     splay(x);
 89     printf("%d\n",x->val);
 90     mask^=x->val;
 91 }
 92 int last,tot,mx[N],par[N],ch[N][26];
 93 void add(int c){
 94     int p=last,np=++tot;mx[np]=mx[p]+1;
 95     for(;p&&!ch[p][c];p=par[p])ch[p][c]=np;
 96     if(!p)par[np]=1;
 97     else{
 98         int q=ch[p][c];
 99         if(mx[q]==mx[p]+1)par[np]=q;
100         else{
101             int nq=++tot;
102             access(&tree[q]);
103             splay(&tree[q]);
104             tree[nq].val=tree[q].val;
105             link(&tree[nq],&tree[par[q]]);
106             cut(&tree[par[q]],&tree[q]);
107             link(&tree[q],&tree[nq]);
108             mx[nq]=mx[p]+1;
109             par[nq]=par[q];
110             memcpy(ch[nq],ch[q],sizeof ch[nq]);
111             par[q]=par[np]=nq;
112             for(;p&&ch[p][c]==q;p=par[p])ch[p][c]=nq;
113         }
114     }
115     link(&tree[np],&tree[par[np]]);
116     update(&tree[np]);
117     last=np;
118 }
119 void gets(int x){
120     scanf("%s",s);
121     n=strlen(s);
122     for(int j=0;j<n;j++){
123         x=(x*131+j)%n;
124         char t=s[j];s[j]=s[x];s[x]=t;
125     }
126 }
127 void dfs(int v,int x){
128     if(x==n){query(&tree[v]);return ;}
129     if(!ch[v][s[x]-'A']){puts("0");return ;}
130     else dfs(ch[v][s[x]-'A'],x+1);
131 }
132 int main(){
133     init();
134     last=++tot;
135     scanf("%d",&m);
136     scanf("%s",s);
137     n=strlen(s);
138     for(int i=0;i<n;i++)add(s[i]-'A');
139     while(m--){
140         scanf("%s",opt);
141         gets(mask);
142         if(opt[0]=='A')for(int i=0;i<n;i++)add(s[i]-'A');
143         else dfs(1,0);
144     }
145     return 0;
146 }
View Code

 

转载于:https://www.cnblogs.com/Ren-Ivan/p/8377047.html

资源下载链接为: https://pan.quark.cn/s/f989b9092fc5 HttpServletRequestWrapper 是 Java Servlet API 中的一个工具类,位于 javax.servlet.http 包中,用于对 HttpServletRequest 对象进行封装,从而在 Web 应用中实现对 HTTP 请求的拦截、修改或增强等功能。通过继承该类并覆盖相关方法,开发者可以轻松地自定义请求处理逻辑,例如修改请求参数、添加请求头、记录日志等。 参数过滤:在请求到达处理器之前,可以对请求参数进行检查或修改,例如去除 URL 编码、过滤敏感信息或进行安全检查。 请求头操作:可以修改或添加请求头,比如设置自定义的 Content-Type 或添加认证信息。 请求属性扩展:在原始请求的基础上添加自定义属性,供后续处理使用。 日志记录:在处理请求前记录请求信息,如 URL、参数、请求头等,便于调试和监控。 跨域支持:通过添加 CORS 相关的响应头,允许来自不同源的请求。 HttpServletRequestWrapper 通过继承 HttpServletRequest 接口并重写其方法来实现功能。开发者可以在重写的方法中添加自定义逻辑,例如在获取参数时进行过滤,或在读取请求体时进行解密。当调用这些方法时,实际上是调用了包装器中的方法,从而实现了对原始请求的修改或增强。 以下是一个简单的示例,展示如何创建一个用于过滤请求参数的包装器: 在 doFilter 方法中,可以使用 CustomRequestWrapper 包装原始请求: 这样,每当调用 getParameterValues 方法时,都会先经过自定义的过滤逻辑。 HttpServletRequestWrapper 是 Java Web 开发中一个强大的工具,它提供了灵活的扩展性,允许开发者
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值