AC自动机_重叠与非重叠匹配

  • 可重叠与不可重叠匹配
      比如模式串为aba,字符串为abababab,若可重叠匹配,那么aba出现的次数为三次;若为不可重叠匹配,那么出现的次数为两次: aba / b / aba /b
       AC自动机对于可重叠匹配很方便,直接顺着节点的fail指针一直走就可以.

不可重叠匹配
Searching the String
题意:
有若干个模式串,然后在字符串中查询它们出现的次数.但是0表示可以重叠出现,1表示不可以重叠出现;
题解:
 假设字典树的每个单词尾节点都有个变量为pos,记录最后一次匹配主串的位置;
 对于可重叠匹配,直接顺着自动机的fail指针一直走;
 对于不可重叠匹配,如果当前正在匹配主串的位置-最后一次成功匹配的字符串的位置大于等于单词的长度,那么这样的匹配是可行的;
 比如模式串为aba,字符串为abababab,第一次匹配到aba的位置为2;第二次匹配到aba位置为4,但是4-2<3,所以这次的匹配是无效的;第三次匹配到aba位置为6,6-2=4>=3,成功匹配;所以最后成功匹配次数为2

/*    这题数据有点恶心,模式串会重复出现
input:
ab
4  
0 ab  
1 ab  
0 ab  
1 ab  
output:
Case 1
1
1
1
1

*/  
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
const int MAXN=100010;
const int BASE=26;
struct Node
{
    int fail;
    int next[26];
    bool ed;
    int len;
    int id1;
    int id2;
    int pos;
    void init()
    {
        fail=0;
        ed=false;
        len=pos=-1;
        id1=id2=0;
        memset(next,0,sizeof(next));
    }
};
Node trie[600005];
int trie_s;
int *x[MAXN];
char str[MAXN];
void put(char *str,int choose,int id)
{
    int p=1;
    int len=strlen(str);
    for(int i=0;i<len;i++)
    {
        int pos=str[i]-'a';
        if(trie[p].next[pos]==0)
        {
            trie[p].next[pos]=++trie_s;
            trie[trie_s].init();
        }
        p=trie[p].next[pos];
    }
    trie[p].ed=true;
    trie[p].len=len;
    if(choose==0)
    {
        x[id]=&(trie[p].id1);
    }
    else x[id]=&(trie[p].id2);
}
void getFail()
{
    queue<int> que;
    int son,p=1,temp;
    que.push(p);
    while(!que.empty())
    {
        int curr=que.front();
        que.pop();
        for(int i=0;i<26;i++)
        {
            son=trie[curr].next[i];
            if(son)
            {
                if(curr==1) trie[son].fail=1;
                else
                {
                    temp=trie[curr].fail;
                    while(temp!=0)
                    {
                        if(trie[temp].next[i])
                        {
                            trie[son].fail=trie[temp].next[i];
                            break;
                        }
                        temp=trie[temp].fail;
                    }
                    if(temp==0) trie[son].fail=1;
                }
                que.push(son);
            }
        }
    }
}
void query(char *str)
{
    int len=strlen(str);
    int p=1,temp;
    for(int i=0;i<len;i++)
    {
        int pos=str[i]-'a';
        while(!trie[p].next[pos]&&p!=1) p=trie[p].fail;
        p=trie[p].next[pos];
        if(p==0) p=1;
        temp=p;
        while(temp!=1)
        {
            if(trie[temp].ed)
            {
                trie[temp].id1=trie[temp].id1+1;
                if(trie[temp].pos==-1||(i-trie[temp].pos>=trie[temp].len))
                {
                    trie[temp].id2=trie[temp].id2+1;
                    trie[temp].pos=i;
                }
            }
            temp=trie[temp].fail;
        }
    }
}
int main()
{
    int n,choose,cas=1;
    char ss[10];
    while(scanf("%s",str)!=EOF)
    {
        scanf("%d",&n);
        trie[1].init();
        trie_s=1;
        for(int i=1;i<=n;i++)
        {
            scanf("%d %s",&choose,ss);
            put(ss,choose,i);
        }
        getFail();
        query(str);
        printf("Case %d\n",cas++);
        for(int i=1;i<=n;i++)
        {
            printf("%d\n",*x[i]);
        }
        printf("\n");
    }
    return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139
  • 引言 字符串匹配一直是计算机科学领域研究和应用的热门领域,算法的改进研究一直是一个十分困难的课题。作为字符串匹配中...
    潮汐行者阅读 1,624评论 2 6
  • 一、字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 s...
    JaiUnChat阅读 1,652评论 0 7
  • 9.19--9.23 第7章 正则表达式 正则表达式是一个拆分字符串并查询相关信息的过程。 推荐练习网站: js ...
    如201608阅读 1,013评论 0 4
  • 有感。爱情的开始并不是两个人多么多么相配,最好的爱情,是一起慢慢地走过,一起进步,一起成熟
    88497ef8823d阅读 115评论 0 0