现在的位置: 首页 > 综合 > 正文

HDU 4125 Moles 笛卡尔树 + kmp

2018年04月25日 ⁄ 综合 ⁄ 共 1991字 ⁄ 字号 评论关闭

题意:有n(1<=n<=600000)个鼹鼠挖洞,每个鼹鼠有给定权值,挖的洞是一颗二叉树(左边的鼹鼠权值都比当前鼹鼠小,右边的鼹鼠权值比当前鼹鼠大),

         也要按照鼹鼠的出场顺序挖洞,在形成的二叉树按照中序遍历顺序奇数偶数(1,0)得到01序列,问01序列中给定的序列出现多少次。

题解:笛卡尔树,k(SBT)为鼹鼠的权值,a(堆)为鼹鼠的编号,排序后O(n)建树之后kmp即可。递归会RE,手动模拟栈。


Sure原创,转载请注明出处

#include <iostream>
#include <cstdio>
#include <memory.h>
#include <algorithm>
using namespace std;
const int maxn = 600002;
const int maxm = 7002;
struct P
{
    int k,a;
    bool operator < (const P &other) const
    {
        return k < other.k;
    }
}mole[maxn];
struct T
{
    int l,r,fa;
}tree[maxn];
int next[maxm],stack[maxn],state[maxn];
char str[maxm],list[maxn * 3];
int n,tot,top;

void init()
{
    memset(tree,0,sizeof(tree));
    memset(state,0,sizeof(state));
    tot = top = 0;
    return;
}

void read()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&mole[i].k);
        mole[i].a = i;
    }
    sort(mole + 1 , mole + n + 1);
    scanf("%s",str);
    return;
}

void rotate(int x)
{
    int p = tree[x].fa;
    int l = tree[x].l;
    if(p == tree[tree[p].fa].l)
    {
        tree[tree[p].fa].l = x;
    }
    else
    {
        tree[tree[p].fa].r = x;
    }
    tree[x].fa = tree[p].fa;
    tree[x].l = p;
    tree[p].fa = x;
    tree[p].r = l;
    if(l) tree[l].fa = p;
    return;
}

void dfs(int st)
{
    stack[top++] = st;
    while(top)
    {
        int cur = stack[top-1];
        list[tot++] = (mole[cur].k & 1) + '0';
        if(++state[cur] == 3)
        {
            top--;
            continue;
        }
        if(state[cur] == 1)
        {
            if(tree[cur].l) stack[top++] = tree[cur].l;
            else state[cur]++;
        }
        if(state[cur] == 2)
        {
            if(tree[cur].r) stack[top++] = tree[cur].r;
            else state[cur]++;
        }
        if(state[cur] == 3) top--;
    }
    return;
}

void make()
{
    tree[0].r = 1;
    int rightmost = 1;
    for(int i=2;i<=n;i++)
    {
        tree[rightmost].r = i;
        tree[i].fa = rightmost;
        rightmost = i;
        while(tree[i].fa && mole[i].a < mole[tree[i].fa].a) rotate(i);
    }
    dfs(tree[0].r);
    list[tot] = '\0';
    return;
}

void getnext(char *s)
{
    int len=strlen(s);
    for(int i=0;i<=len;i++)
    {
        next[i] = 0;
    }
    next[0] = -1;
    int j=-1;
    for(int i=0;i<len;)
    {
        if(j==-1||s[i]==s[j])
        {
            i++;
            j++;
            next[i]=j;
        }
        else j=next[j];
    }
    return;
}

int kmp(char a[],char b[])
{
    int count=0;
    getnext(b);
    int lena = strlen(a);
    int lenb = strlen(b);
    int j=0,i=0;
    while(i<lena && j<lenb)
    {
        if(j==-1 || b[j]==a[i])
        {
            j++;
            i++;
        }
        else j=next[j];
        if(j == lenb)
        {
            count++;
            j = next[j];
        }
    }
    return count;
}

int main()
{
    int cas;
    scanf("%d",&cas);
    for(int i=1;i<=cas;i++)
    {
        printf("Case #%d: ",i);
        init();
        read();
        make();
        printf("%d\n",kmp(list,str));
    }
    return 0;
}

抱歉!评论已关闭.