字典树习题(更新ing)

洛谷P2580(板子题)
原题链接
直接套用板子,将flag改为int型,0表示未出现,输出WRONG,1表示第一次出现输出OK并将其变为2,2输出REPEAT

代码如下

/*********************************************************************/
/**********************************cyf*******************************/
/*******************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i,x) for(int i=0;i
#define ll long long
#define repp(i,x) for(int i=1;i<=x;i++)
#define repx(i,n,j) for(int i=j;i
const ll mod=1e9+7;

bool shushu(int x)
{
    int flag=0;
    for(int i=2;i*i<=x;i++)
    {
        if(x%i==0)
        {
            flag=1;
            break;
        }
    }
    if(flag)
        return false;
    else
        return true;
}
int gcd(int x,int y)
{
    int t;
    while(y%x!=0)
    {
        t=y%x;
        y=x;
        x=t;
    }
    return x;
}
int lcm(int x,int y)
{
    return x/gcd(x,y)*y;
}
ll q_pow(ll a,ll b,int m)//
{
    ll r=1,base=a;
    while(b!=0){
        if(b%2)
          r*=base;
        r%=m;
        base*=base;
        base%=m;
        b/=2;
    }
    return r;
}
const int maxn=2e6+5;
int totle;
int tree[maxn][30];
int flag[maxn];

void init_(char*str)
{
    int len=strlen(str),root=0,id;
    rep(i,len)
    {
        id=str[i]-'a';
        if(!tree[root][id])
            tree[root][id]=++totle;
        root=tree[root][id];
    }
    flag[root]=1;
}

void find_(char*str)
{
    int len=strlen(str),root=0,id;
    rep(i,len)
    {
        id=str[i]-'a';
        if(!tree[root][id])
        {
            cout<<"WRONG"<<endl;
            return;
        }
        root=tree[root][id];
    }
    if(flag[root]==1)
    {
        cout<<"OK"<<endl;
        flag[root]=2;
    }
    else
        cout<<"REPEAT"<<endl;
}
char s[maxn];
int main()
{
    int n,m;
    cin>>n;
    repp(i,n)
    {
        cin>>s;
        init_(s);
    }
    cin>>m;
    repp(i,m)
    {
        cin>>s;
        find_(s);
    }
    return 0;
}

洛谷P5149

先用字典树按第一个顺序,求出每个老师的编号,然后就要求第二个顺序中逆序个数,此时可用归并排序,当a[i]>a[j],ans+=mid-i,ans要开ll,不然最后四个测试点会wa代码如下

/*********************************************************************/
/**********************************cyf*******************************/
/*******************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i,x) for(int i=0;i
#define ll long long
#define repp(i,x) for(int i=1;i<=x;i++)
#define repx(i,n,j) for(int i=j;i
const ll mod=1e9+7;

bool shushu(int x)
{
    int flag=0;
    for(int i=2;i*i<=x;i++)
    {
        if(x%i==0)
        {
            flag=1;
            break;
        }
    }
    if(flag)
        return false;
    else
        return true;
}
int gcd(int x,int y)
{
    int t;
    while(y%x!=0)
    {
        t=y%x;
        y=x;
        x=t;
    }
    return x;
}
int lcm(int x,int y)
{
    return x/gcd(x,y)*y;
}
ll q_pow(ll a,ll b,int m)//
{
    ll r=1,base=a;
    while(b!=0){
        if(b%2)
          r*=base;
        r%=m;
        base*=base;
        base%=m;
        b/=2;
    }
    return r;
}


const int maxn=2e6+5;
int tree[maxn][60];
int flag[maxn];
int totle=0,js=0;
ll ans;

void init_(char*str)
{
    int root=0,id,len=strlen(str);
    rep(i,len)
    {
        if(str[i]>='a' && str[i]<='z')
            id=str[i]-'a';
        else
            id=str[i]-'A'+'z'-'a'+1;
        if(!tree[root][id])
            tree[root][id]=++totle;
        root=tree[root][id];
    }
    flag[root]=++js;
}
int find_(char*str)
{
    int root=0,id,len=strlen(str);
    rep(i,len)
    {
        if(str[i]>='a' && str[i]<='z')
            id=str[i]-'a';
        else
            id=str[i]-'A'+'z'-'a'+1;
        root=tree[root][id];
    }
    return flag[root];
}
void hb(int*s,int l,int mid,int r)
{
    int b[100005];
    int i=l,j=mid,k=0;
    while(i<mid && j<=r)
    {
        if(s[i]<=s[j])
            b[k++]=s[i++];
        else{
            b[k++]=s[j++];
            ans+=mid-i;
        }
    }
    while(i<mid) b[k++]=s[i++];
    while(j<=r) b[k++]=s[j++];
    for(int ii=l;ii<=r;ii++)
        s[ii]=b[ii-l];
}
void gb(int*s,int l,int r)
{
    if(l==r) return;
    int mid=(l+r)/2;
    gb(s,l,mid);
    gb(s,mid+1,r);
    hb(s,l,mid+1,r);
}
char a[10];
int A[100005];
int main()
{
    int n;
    cin>>n;
    ans=0;
    repp(i,n)
    {
        cin>>a;
        init_(a);
    }
    repp(i,n)
    {
        cin>>a;
        A[i]=find_(a);
    }
    gb(A,1,n);
    cout<<ans<<endl;
    return 0;
}

洛谷p2922

又是一道板子题
由于说的是暗号和信息最小的为标准,所以查找某条暗号时,从其第一项开始,将每一项中flag数相加,最后一项时,还要额外加上以其为后缀的信息数k(不包括刚好等于的),k=sum[root]-flag[root]
代码如下

/*********************************************************************/
/**********************************cyf*******************************/
/*******************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i,x) for(int i=0;i
#define ll long long
#define repp(i,x) for(int i=1;i<=x;i++)
#define repx(i,n,j) for(int i=j;i
const ll mod=1e9+7;

bool shushu(int x)
{
    int flag=0;
    for(int i=2;i*i<=x;i++)
    {
        if(x%i==0)
        {
            flag=1;
            break;
        }
    }
    if(flag)
        return false;
    else
        return true;
}
int gcd(int x,int y)
{
    int t;
    while(y%x!=0)
    {
        t=y%x;
        y=x;
        x=t;
    }
    return x;
}
int lcm(int x,int y)
{
    return x/gcd(x,y)*y;
}
ll q_pow(ll a,ll b,int m)//
{
    ll r=1,base=a;
    while(b!=0){
        if(b%2)
          r*=base;
        r%=m;
        base*=base;
        base%=m;
        b/=2;
    }
    return r;
}


const int maxn=2e6+5;
int tree[maxn][2];
int flag[maxn];
ll sum[maxn];
int totle=0;

void init_(int*str,int len)
{
    int root=0,id;
    rep(i,len)
    {
        id=str[i];
        if(!tree[root][id])
            tree[root][id]=++totle;
        root=tree[root][id];
        sum[root]+=1;
    }
    flag[root]+=1;
}

ll find_(int*str,int len)
{
    int root=0,id;
    ll ans=0;
    rep(i,len)
    {
        id=str[i];
        if(!tree[root][id])
            return ans;
        root=tree[root][id];
        ans+=flag[root];
    }
    ans+=sum[root]-flag[root];
    return ans;
}
int a[10005];
int main()
{
    int n,m,k;
    cin>>n>>m;
    repp(i,n)
    {
        cin>>k;
        repp(j,k)
        cin>>a[j];
        init_(a+1,k);
    }
    repp(i,m)
    {
        cin>>k;
        repp(j,k)
        cin>>a[j];
        cout<<find_(a+1,k)<<endl;
    }
    return 0;
}

你可能感兴趣的:(字典树)