SGU 505. Prefixes and suffixes

就是给你一大堆字符串,然后每次询问以一个给定串为前缀,
一个给定串为后缀的字符串有几个?
我是一直没有思路的,但是在做出网易比赛的拿到有道搜索框之后
我就已经知道算法了。。但是
一直WA,今天才发现是犯了个SB错误囧啊。。。
是这样的,将所有字符串排序,由那题我明白了所有由某个前缀的字符串是一个区间,
然后将所有字符串
全部反过来排序,那么由某个后缀的字符串也是一个区间,把这些字符串都标上其在
第一遍排序中的排名。。那么问题就成了,在[a,b]中,[l,r]之间的数有几个。。
那么由两种办法,一种是在线算法,就是建个线段树,那么是LogN^2的。。
另一种就是离线算法,只需要一个树状数组就OK了。。。
鉴于第一个可能TLE。。所以我用了离线算法。。编写上需要注意一些东西。。
我发现关于string的话,cin还是蛮快的。。
Code:
include<string>
#include<algorithm>
#include<iostream>
#include<vector>
#include<cstring>
#include<cstdio>
#define pb push_back
#define Rep(i,n) for(int i=0;i<n;i++)
#define All(x) x.begin(),x.end()
#define tr(e,x) for(typeof(x.begin()) e=x.begin();e!=x.end();e++)
using namespace std;
const int maxn=100000,maxm=100000;
string S[maxn],R[maxn];
int n,m,Ans[maxm]={},A[maxn];
struct Data
{
    int l,r,num,d;
    Data(int _l,int _r,int _num,int _d):l(_l),r(_r),num(_num),d(_d){}
};
vector<Data> E[maxn];
bool AsPrefix(const string&str,const string&prefix)
{
    if(str.size()<prefix.size()||str.substr(0,prefix.size())!=prefix)
        return false;
    return true;
}
void get(string S[maxn],string pre,int&l,int&r)
{
    l=lower_bound(S,S+n,pre)-S;
    pre[pre.size()-1]++;
    r=lower_bound(S,S+n,pre)-S;
}
struct TreeArray
{
    int H[maxn+10];
    TreeArray(){memset(H,0,sizeof(H));}
    void Add(int l,int d)
    {
        l++;
        for(;l<=n;l+=(l&-l))
            H[l]+=d;
    }
    int operator[](int l)
    {
        l++;int ret=0;
        for(;l>0;l-=(l&-l))
            ret+=H[l];
        return ret;
    }
}T;
int main()
{
    //freopen("in","r",stdin);
    cin>>n;Rep(i,n)cin>>S[i],R[i]=S[i],reverse(All(R[i]));
    sort(S,S+n);sort(R,R+n);
    Rep(i,n)
    {
        string tmp=R[i];reverse(All(tmp));
        A[i]=lower_bound(S,S+n,tmp)-S;
    }
    cin>>m;string Pre,Suf;
    Rep(i,m)
    {
        cin>>Pre>>Suf;
        int l,r,a,b;
        get(S,Pre,l,r);
        if(l==r)continue;
        reverse(All(Suf));
        get(R,Suf,a,b);
        if(a==b)continue;
        E[b-1].pb(Data(l,r-1,i,1));
        if(a)E[a-1].pb(Data(l,r-1,i,-1));
    }
    Rep(i,n)
    {
        T.Add(A[i],1);
        tr(e,E[i])Ans[e->num]+=(T[e->r]-T[e->l-1])*e->d;
    }
    Rep(i,m)printf("%dn",Ans[i]);
}

3 thoughts on “SGU 505. Prefixes and suffixes

Leave a Reply

Your email address will not be published. Required fields are marked *