传送门
解析:
SAM基础操作。
解析:
其实不管其他的单独看后缀链接,即 f a fa fa指针或 f a i l fail fail指针的话,其实这个 f a i l fail fail就是 K M P KMP KMP里面的 n x t nxt nxt数组,所以添加一个字符后新的子串有多少个,直接用自己的 l e n len len去减去父亲的 l e n len len就可以了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
namespace IO{
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
inline void outint(int a){
static char ch[23];
if(a==0)pc('0');
while(a)ch[++ch[0]]=a-a/10*10,a/=10;
while(ch[0])pc(ch[ch[0]--]^48);
}
}
using namespace IO;
typedef struct SAM_node *point;
struct SAM_node{
int len;
point fa,son[26];
SAM_node():fa(NULL),len(0){memset(son,0,sizeof son);}
inline point clear(int l=0){
fa=NULL;
len=l;
memset(son,0,sizeof son);
return this;
}
};
cs int N=2003;
struct SAM{
SAM_node nd[N<<1];
point now,last;
int strnum;
SAM():now(nd),last(nd),strnum(0){}
inline void clear(){
for(;now>nd;--now)now->clear();
now=last=nd->clear();
strnum=0;
}
inline void push_back(char c){
c-='a';
point cur=++now;
cur->len=last->len+1;
point p=last;
for(;p&&!p->son[c];p=p->fa)p->son[c]=cur;
if(!p)cur->fa=nd;
else if(p->son[c]->len==p->len+1)cur->fa=p->son[c];
else {
point clone=++now,q=p->son[c];
*clone=*q;
clone->len=p->len+1;
q->fa=cur->fa=clone;
for(;p&&p->son[c]==q;p=p->fa)p->son[c]=clone;
}
last=cur;
strnum+=cur->len-cur->fa->len;
}
}sam;
int T,q;
char s[N];int len;
int ans[N][N];
signed main(){
T=getint();
while(T--){
scanf("%s",s+1);len=strlen(s+1);
for(int re i=1;i<=len;++i){
sam.clear();
for(int re j=i;j<=len;++j){
sam.push_back(s[j]);
ans[i][j]=sam.strnum;
}
}
q=getint();
while(q--){
int x=getint(),y=getint();
outint(ans[x][y]);pc('\n');
}
}
return 0;
}