題目鏈接:點擊查看
題目大意:給出 n 個字符串,再給出 m 次詢問,每次詢問需要輸出區間 [ l , r ] 內的所有字符串有多少個不同的前綴,要求算法強制在線
題目分析:統計字符串的前綴,不難想到藉助字典樹實現,再將問題簡化爲在線求區間 [ l , r ] 內不同數字的個數,這就是主席樹的基本應用了,兩個模板搭配起來就是這個問題的答案了
代碼:
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const int N=1e5+100;
/*主席樹*/
struct Node
{
int l,r;
int sum;
}tree[N*40];
int cnt,root[N];
void change(int pos,int &k,int l,int r,int val)
{
tree[cnt++]=tree[k];
k=cnt-1;
tree[k].sum+=val;
if(l==r)
return;
int mid=l+r>>1;
if(pos<=mid)
change(pos,tree[k].l,l,mid,val);
else
change(pos,tree[k].r,mid+1,r,val);
}
int query(int rt,int pos,int l,int r)
{
if(l==r)
return tree[rt].sum;
int mid=l+r>>1;
if(pos<=mid)
return tree[tree[rt].r].sum+query(tree[rt].l,pos,l,mid);
else
return query(tree[rt].r,pos,mid+1,r);
}
/*主席樹*/
/*字典樹*/
string s[N];
int k;
int trie[N][26];//儲存每一條邊 trie[節點數][字符數]
int pre[N];//判斷某一個字符串是否出現過
int newnode()
{
k++;
for(int i=0;i<26;i++)
trie[k][i]=0;
pre[k]=0;
return k;
}
void insert(string& s)//插入
{
int pos=0;
for(int i=0;i<s.size();i++)
{
int to=s[i]-'a';
if(!trie[pos][to])
trie[pos][to]=newnode();
pos=trie[pos][to];
}
}
void search(string& s,int id,int n)//查找
{
int pos=0;
for(int i=0;i<s.size();i++)
{
int to=s[i]-'a';
pos=trie[pos][to];
if(pre[pos])
change(pre[pos],root[id],1,n,-1);
change(id,root[id],1,n,1);
pre[pos]=id;
}
}
/*字典樹*/
void init()
{
root[0]=0;
tree[0].l=tree[0].r=tree[0].sum=0;
cnt=1;
k=-1;
newnode();
}
int main()
{
#ifndef ONLINE_JUDGE
// freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);
int n;
while(scanf("%d",&n)!=EOF)
{
init();
for(int i=1;i<=n;i++)
{
cin>>s[i];
insert(s[i]);
}
for(int i=1;i<=n;i++)
{
root[i]=root[i-1];
search(s[i],i,n);
}
int m;
scanf("%d",&m);
int ans=0;
while(m--)
{
int l,r;
scanf("%d%d",&l,&r);
l=(l+ans)%n+1;
r=(r+ans)%n+1;
if(l>r)
swap(l,r);
printf("%d\n",ans=query(root[r],l,1,n));
}
}
return 0;
}