[AC自动机] zoj Searching the String

题意:

给一个原串,再给n个串,每个串有属性,属性0代表可以重叠,1代表不可以重叠

问每个串出现了多少次

思路:

为了方便建立两个自动机(0的一个,1的一个)

然后可以重叠的很好做,以前都做过

不可重叠的话需要记录两个东西

len[i]代表每个串的长度,used[i]代表每个串在之前出现的位置,初始化-1

然后遍历到的时候对于当前位置 j, 必须j>=used[i]+len[i] 才能算出现,并且更新

需要注意的是:

会出现同样属性并且相同的串。我处理的方式就是排序,按id排序大的在前

然后算一遍大的,用大的赋值给id 小的且串相同的。

代码:

#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"iostream"
using namespace std;
char fuck[123456];
int ans[123456],used[123456],len[123456];
struct word
{
    int x,id;
    char y[7];
} dc[123456];
struct trie
{
    int mark;
    trie *next[27];
    trie *fail;
    trie()
    {
        mark=0;
        memset(next,0,sizeof(next));
        fail=NULL;
    }
};
trie *root0,*root1;
void init(int key,char *v,int id)
{
    trie *p;
    if(key) p=root1;
    else p=root0;
    for(int i=0; v[i]; i++)
    {
        int tep=v[i]-'a';
        if(p->next[tep]==NULL) p->next[tep]=new trie();
        p=p->next[tep];
    }
    p->mark=id;
}
void del(trie *p)
{
    for(int j=0; j<26; j++) if(p->next[j]!=NULL) del(p->next[j]);
    free(p);
}
void getac()
{
    queue<trie*>q;
    q.push(root0);
    while(!q.empty())
    {
        trie *p,*tep;
        p=q.front();
        q.pop();
        for(int i=0; i<26; i++)
        {
            if(p->next[i]!=NULL)
            {
                if(p==root0) p->next[i]->fail=root0;
                else
                {
                    tep=p->fail;
                    while(tep!=NULL)
                    {
                        if(tep->next[i]!=NULL)
                        {
                            p->next[i]->fail=tep->next[i];
                            break;
                        }
                        tep=tep->fail;
                    }
                    if(tep==NULL) p->next[i]->fail=root0;
                }
                q.push(p->next[i]);
            }
        }
    }
    q.push(root1);
    while(!q.empty())
    {
        trie *p,*tep;
        p=q.front();
        q.pop();
        for(int i=0; i<26; i++)
        {
            if(p->next[i]!=NULL)
            {
                if(p==root1) p->next[i]->fail=root1;
                else
                {
                    tep=p->fail;
                    while(tep!=NULL)
                    {
                        if(tep->next[i]!=NULL)
                        {
                            p->next[i]->fail=tep->next[i];
                            break;
                        }
                        tep=tep->fail;
                    }
                    if(tep==NULL) p->next[i]->fail=root1;
                }
                q.push(p->next[i]);
            }
        }
    }
}
void finde(char *v)
{
    trie *p0=root0,*p1=root1;
    for(int i=0; v[i]; i++)
    {
        int tep=v[i]-'a';
        while(p0->next[tep]==NULL && p0!=root0)
            p0=p0->fail;
        p0=p0->next[tep];
        if(p0==NULL) p0=root0;
        trie *q0=p0;
        while(q0!=root0)
        {
            if(q0->mark!=0) ans[q0->mark]++;
            q0=q0->fail;
        }
        while(p1->next[tep]==NULL && p1!=root1)
            p1=p1->fail;
        p1=p1->next[tep];
        if(p1==NULL) p1=root1;
        trie *q1=p1;
        while(q1!=root1)
        {
            if(q1->mark!=0)
            {
                if(i>=used[q1->mark]+len[q1->mark])  //不可重叠的判断
                {
                    ans[q1->mark]++;
                    used[q1->mark]=i;
                }
            }
            q1=q1->fail;
        }
    }
}
int cmp(word a,word b)  //排序的cmp
{
    if(a.x==b.x)
    {
        if(strcmp(a.y,b.y)==0)
        {
            if(a.id>b.id) return 1;
            else return 0;
        }
        else
        {
            if(strcmp(a.y,b.y)>0) return 1;
            else return 0;
        }
    }
    else
    {
        if(a.x>b.x) return 1;
        else return 0;
    }
}
int main()
{
    int cas=1;
    while(scanf("%s",fuck)!=-1)
    {
        int n;
        scanf("%d",&n);
        root0=new trie();
        root1=new trie();
        for(int i=1; i<=n; i++)
        {
            int x;
            char y[12];
            scanf("%d%s",&x,y);
            len[i]=strlen(y);
            init(x,y,i);
            dc[i].x=x;
            strcpy(dc[i].y,y);
            dc[i].id=i;
        }
        memset(ans,0,sizeof(ans));
        memset(used,-1,sizeof(used));
        getac();
        finde(fuck);
        sort(dc+1,dc+1+n,cmp);
        int i;
        for(i=1; dc[i+1].x==1; i++)  //赋值给那些重复的
        {
            if(strcmp(dc[i].y,dc[i+1].y)==0)
                ans[dc[i+1].id]=ans[dc[i].id];
        }
        for(i=i+1; i<n; i++)
        {
            if(strcmp(dc[i].y,dc[i+1].y)==0)
                ans[dc[i+1].id]=ans[dc[i].id];
        }
        printf("Case %d\n",cas++);
        for(int i=1; i<=n; i++) printf("%d\n",ans[i]);
        del(root0);
        del(root1);
        puts("");
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GeoPandas是一个开源的Python库,旨在简化地理空间数据的处理和分析。它结合了Pandas和Shapely的能力,为Python用户提供了一个强大而灵活的工具来处理地理空间数据。以下是关于GeoPandas的详细介绍: 一、GeoPandas的基本概念 1. 定义 GeoPandas是建立在Pandas和Shapely之上的一个Python库,用于处理和分析地理空间数据。 它扩展了Pandas的DataFrame和Series数据结构,允许在其中存储和操作地理空间几何图形。 2. 核心数据结构 GeoDataFrame:GeoPandas的核心数据结构,是Pandas DataFrame的扩展。它包含一个或多个列,其中至少一列是几何列(geometry column),用于存储地理空间几何图形(如点、线、多边形等)。 GeoSeries:GeoPandas中的另一个重要数据结构,类似于Pandas的Series,但用于存储几何图形序列。 二、GeoPandas的功能特性 1. 读取和写入多种地理空间数据格式 GeoPandas支持读取和写入多种常见的地理空间数据格式,包括Shapefile、GeoJSON、PostGIS、KML等。这使得用户可以轻松地从各种数据源中加载地理空间数据,并将处理后的数据保存为所需的格式。 2. 地理空间几何图形的创建、编辑和分析 GeoPandas允许用户创建、编辑和分析地理空间几何图形,包括点、线、多边形等。它提供了丰富的空间操作函数,如缓冲区分析、交集、并集、差集等,使得用户可以方便地进行地理空间数据分析。 3. 数据可视化 GeoPandas内置了数据可视化功能,可以绘制地理空间数据的地图。用户可以使用matplotlib等库来进一步定制地图的样式和布局。 4. 空间连接和空间索引 GeoPandas支持空间连接操作,可以将两个GeoDataFrame按照空间关系(如相交、包含等)进行连接。此外,它还支持空间索引,可以提高地理空间数据查询的效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值