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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章