HDU - 5790 Prefix(主席树+字典树)

题目链接:点击查看

题目大意:给出 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;
}

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/106866972