回文自动机好题啊!
解法一
每$sqrt n (分一块
每块建回文自动机到字符串末尾。
顺便开三个)sqrt n * n(的数组记下预处理答案,回文自动机头指针,和每个节点第一次出现的右端点
询问的时候回文自动机前端添加,算出答案。
貌似不能写均摊复杂度的回文自动机,只能写单次复杂度有证明的。
设)T(为字符集大小
时间复杂度)O(Tn+n sqrt n)$
#include <bits/stdc++.h>
using namespace std;
const int N=100010,D=320;
int pre[D][N],preworkans[D][N],firstappear[D][N],vis[N];
struct pam{
struct pamnode{
int len,fa,anc[26],trans[26];
}T[N];
int tot,fi,la;
pam(){
T[1].len=-1;
T[0].fa=1;
for (int j=0; j<26; ++j) T[0].anc[j]=1;
tot=1;
fi=0;
la=0;
}
void pushback(char *s,int l,int r){
int c=s[r]-'a';
if (r-T[la].len-1<l||s[r]!=s[r-T[la].len-1]) la=T[la].anc[c];
if (!T[la].trans[c]){
int q=++tot,k=T[la].fa;
T[q].len=T[la].len+2;
if (r-T[k].len-1<l||s[r]!=s[r-T[k].len-1]) T[q].fa=T[T[k].anc[c]].trans[c];
else T[q].fa=T[k].trans[c];
memcpy(T[q].anc,T[T[q].fa].anc,sizeof(T[q].anc));
T[q].anc[s[r-T[T[q].fa].len]-'a']=T[q].fa;
T[la].trans[c]=q;
}
la=T[la].trans[c];
if (T[la].len==r-l+1) fi=la;
}
void pushfront(char *s,int l,int r){
int c=s[l]-'a';
if (l+T[fi].len+1>r||s[l]!=s[l+T[fi].len+1]) fi=T[fi].anc[c];
if (!T[fi].trans[c]){
int q=++tot,k=T[fi].fa;
T[q].len=T[fi].len+2;
if (l+T[k].len+1>r||s[l]!=s[l+T[k].len+1]) T[q].fa=T[T[k].anc[c]].trans[c];
else T[q].fa=T[k].trans[c];
memcpy(T[q].anc,T[T[q].fa].anc,sizeof(T[q].anc));
T[q].anc[s[l+T[T[q].fa].len]-'a']=T[q].fa;
T[fi].trans[c]=q;
}
fi=T[fi].trans[c];
if (T[fi].len==r-l+1) la=fi;
}
}A;
int ty,n,q,S,clk,ans;
char s[N];
int main(){
scanf("%d%d%d%s",&ty,&n,&q,s+1);
S=sqrt(n);
for (int i=0; i*S+1<=n; ++i){
A.fi=A.la=0; ++clk;
for (int j=i*S+1; j<=n; ++j){
A.pushback(s,i*S+1,j);
preworkans[i][j]=preworkans[i][j-1];
if (vis[A.la]<clk){
vis[A.la]=clk;
firstappear[i][A.la]=j;
++preworkans[i][j];
}
pre[i][j]=A.fi;
}
}
while (q--){
int l,r;
scanf("%d%d",&l,&r);
l^=(ty*ans);
r^=(ty*ans);
++clk;
if ((l-1)/S==(r-1)/S){
A.fi=A.la=0;
ans=0;
for (int i=l; i<=r; ++i){
A.pushback(s,l,i);
if (vis[A.la]<clk){
vis[A.la]=clk;
++ans;
}
}
}
else{
int L=(l-1)/S+1-(l%S==1);
A.fi=pre[L][r];
ans=preworkans[L][r];
for (int i=L*S; i>=l; --i){
A.pushfront(s,i,r);
if (vis[A.fi]<clk){
vis[A.fi]=clk;
if (firstappear[L][A.fi]>r||firstappear[L][A.fi]==0) ++ans;
}
}
}
cout<<ans<<'
';
}
}
解法2
记回文自动机上一个节点的串长为(len(x)),父节点为(fa(x)),则对于回文树上一条链,从叶子到根,(len(x)-len(fa(x)))递减,且只有(log)种取值,也就是说,可以分成(log)个等差数列。
主席树维护扫描右端点时左端点的答案,一个等差数列就是一个区间加。
时间复杂度(O(nlog^2(n)))
#include <bits/stdc++.h>
using namespace std;
#define debug(x) cerr<<#x<<":"<<x<<endl
const int N=100010;
const int P=270010;
const int D=17*17*N;
struct zkw{
int u,st[P];
void init(int len){
for (u=1; u<len; u<<=1);
--u;
}
void mark(int s,int t){
//cerr<<"Mark"<<s<<" "<<t<<endl;
for (s+=u; s; s>>=1) st[s]=max(st[s],t);
}
int ask(int s,int t){
//cerr<<"ask"<<s<<" "<<t<<endl;
int ret=0;
for (s+=u-1,t+=u+1; s^t^1; s>>=1,t>>=1){
if (~s&1) ret=max(ret,st[s^1]);
if (t&1) ret=max(ret,st[t^1]);
}
//debug(ret);
return ret;
}
}seg1;
struct president{
int ll,rr,tot;
struct presidentnode{
int l,r,v;
}T[D];
void add(int &ind,int l,int r){
/*if (l!=13||r!=12){
debug(l); debug(r); debug(tot);
debug(ll); debug(rr);
}*/
T[++tot]=T[ind];
ind=tot;
//cerr<<"CC"<<endl;
if (ll<=l&&r<=rr) return void(++T[ind].v);
int mid=(l+r)>>1;
if (ll<=mid) add(T[ind].l,l,mid);
if (mid<rr) add(T[ind].r,mid+1,r);
}
int ask(int ind,int l,int r){
if (l==r) return T[ind].v;
int mid=(l+r)>>1;
return (ll<=mid?ask(T[ind].l,l,mid):ask(T[ind].r,mid+1,r))+T[ind].v;
}
}seg2;
struct pam{
vector<int> g[N];
struct pamnode{
int fa,len,d,df,trans[26];
}T[N];
int la,tot,dfn[N],clk,lst[N];
pam(){
T[1].len=-1;
T[0].fa=1;
T[0].d=-1;
tot=1;
la=0;
}
int pushback(char *s,int l,int r){
int c=s[r]-'a';
while (r-T[la].len-1<l||s[r]!=s[r-T[la].len-1]) la=T[la].fa;
if (!T[la].trans[c]){
int q=++tot,k=T[la].fa;
T[q].len=T[la].len+2;
while (r-T[k].len-1<l||s[r]!=s[r-T[k].len-1]) k=T[k].fa;
T[q].fa=T[k].trans[c];
T[la].trans[c]=q;
T[q].d=(T[q].fa?T[q].len-T[T[q].fa].len:0);
T[q].df=(T[q].d==T[T[q].fa].d?T[T[q].fa].df:q);
}
return la=T[la].trans[c];
}
void dfs(int x){
//debug(x); debug(fa);
dfn[x]=clk++;
for (auto i:g[x]) dfs(i);
lst[x]=clk-1;
}
void prework(){
for (int i=tot; i>1; --i) g[T[i].fa].push_back(i);
dfs(0);
}
}A;
int ty,n,q,ans,rt[N],rec[N];
char s[N];
void build(){
//for (int i=1; i<=A.tot; ++i) debug(A.dfn[i]);
seg1.init(A.tot);
for (int i=1; i<=n; ++i){
rt[i]=rt[i-1];
int x=rec[i];
while (x>1){
seg2.ll=max(seg1.ask(A.dfn[x],A.lst[x])-A.T[x].len+2,1);
seg2.rr=i-A.T[A.T[x].df].len+1;
//cerr<<"plus"<<i<<" "<<seg2.ll<<" "<<seg2.rr<<" "<<A.T[x].df<<" "<<A.T[x].len<<endl;
seg2.add(rt[i],1,n);
x=A.T[A.T[x].df].fa;
}
seg1.mark(A.dfn[rec[i]],i);
}
}
int main(){
scanf("%d%d%d%s",&ty,&n,&q,s+1);
for (int i=1; i<=n; ++i) rec[i]=A.pushback(s,1,i)/*,debug(rec[i]),debug(A.T[rec[i]].fa)*/;
A.prework();
build();
while (q--){
int l,r;
scanf("%d%d",&l,&r);
l^=(ty*ans);
r^=(ty*ans);
seg2.ll=l;
cout<<(ans=seg2.ask(rt[r],1,n))<<'
';
}
}