题意:给出一个字符串,最长2000,Q个询问,每次询问[L,R]区间内有多少个不同的字串。
可以用后缀自动机做,也可以先把字符串Hash成一个个整数,转化成求一个区间内不同的整数个数。用Trie树Hash超内存了。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned int uint;
struct hash_map
{
const static int mod=2000007;
int head[mod],nEle;
struct node
{
uint key1,key2;
int key3,pos,pre;
node(){}
node(uint key1,uint key2,int key3,int pos,int pre) :
key1(key1),key2(key2),key3(key3),pos(pos),pre(pre) {}
}ele[2000000];
void init()
{
nEle=0;
memset(head,-1,sizeof(head));
}
void clear()
{
for(int i=0;i<nEle;i++)
head[ele[i].key1%mod]=-1;
nEle=0;
}
int find(uint key1,uint key2,int len)
{
int hashcode=key1%mod;
for(int i=head[hashcode];i!=-1;i=ele[i].pre)
if(ele[i].key1==key1&&ele[i].key2==key2&&ele[i].key3==len)
return i;
return -1;
}
int getPos(uint key1,uint key2,int len)
{
int pos=find(key1,key2,len);
if(pos==-1) return -1;
return ele[pos].pos;
}
void updata(uint key1,uint key2,int len,int pos)
{
int idx=find(key1,key2,len);
if(idx==-1)
{
int tmp=key1%mod;
ele[nEle]=node(key1,key2,len,pos,head[tmp]);
head[tmp]=nEle++;
}
else ele[idx].pos=pos;
}
}hash;
int T[2100],LIM;
int lowbit(int x) { return x&(-x); }
void add(int idx1,int idx2)
{
//cout<<idx1<<" "<<idx2<<endl;
for(int i=idx1;i<=LIM;i+=lowbit(i)) T[i]+=1;
for(int i=idx2+1;i<=LIM;i+=lowbit(i)) T[i]-=1;
}
int query(int idx)
{
if(idx<=0) return 0;
int sum=0;
for(int i=idx;i>0;i-=lowbit(i)) sum+=T[i];
return sum;
}
struct OP
{
int st,ed,id;
OP(){}
OP(int st,int ed,int id) :
st(st),ed(ed),id(id) {}
bool operator<(const OP &B)const
{
return ed<B.ed;
}
}op[10005];
const int MaxLen=2100;
const int mut1=127;
const int mut2=131;
int res[10005];
int main()
{
int t;
scanf("%d",&t);
hash.init();
while(t--)
{
char s[MaxLen];
scanf("%s",s+1);
int len=(int)strlen(s+1);
hash.clear();
LIM=len;
for(int i=1;i<=len;i++) T[i]=0;
int Q; scanf("%d",&Q);
for(int i=0;i<Q;i++)
{
int st,ed; scanf("%d%d",&st,&ed);
op[i]=OP(st,ed,i);
}
sort(op,op+Q);
int ind=0;
for(int i=1;i<=len;i++)
{
uint key1=0,key2=0;
for(int j=i;j>=1;j--)
{
key1=key1*mut1+s[j];
key2=key2*mut2+s[j];
int pos=hash.getPos(key1,key2,i-j+1);
if(pos==-1) pos=0;
add(pos+1,j);
hash.updata(key1,key2,i-j+1,j);
}
while(ind<Q&&op[ind].ed==i)
{
res[op[ind].id]=query(op[ind].st);
ind++;
}
}
for(int i=0;i<Q;i++) printf("%d\n",res[i]);
}
return 0;
}