AC自動機(jī)_重疊與非重疊匹配

  • 可重疊與不可重疊匹配
      比如模式串為aba,字符串為abababab,若可重疊匹配,那么aba出現(xiàn)的次數(shù)為三次;若為不可重疊匹配,那么出現(xiàn)的次數(shù)為兩次: aba / b / aba /b
       AC自動機(jī)對于可重疊匹配很方便,直接順著節(jié)點(diǎn)的fail指針一直走就可以.

不可重疊匹配
Searching the String
題意:
有若干個(gè)模式串,然后在字符串中查詢它們出現(xiàn)的次數(shù).但是0表示可以重疊出現(xiàn),1表示不可以重疊出現(xiàn);
題解:
 假設(shè)字典樹的每個(gè)單詞尾節(jié)點(diǎn)都有個(gè)變量為pos,記錄最后一次匹配主串的位置;
 對于可重疊匹配,直接順著自動機(jī)的fail指針一直走;
 對于不可重疊匹配,如果當(dāng)前正在匹配主串的位置-最后一次成功匹配的字符串的位置大于等于單詞的長度,那么這樣的匹配是可行的;
 比如模式串為aba,字符串為abababab,第一次匹配到aba的位置為2;第二次匹配到aba位置為4,但是4-2<3,所以這次的匹配是無效的;第三次匹配到aba位置為6,6-2=4>=3,成功匹配;所以最后成功匹配次數(shù)為2

/*    這題數(shù)據(jù)有點(diǎn)惡心,模式串會重復(fù)出現(xiàn)
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;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,993評論 19 139
  • 引言 字符串匹配一直是計(jì)算機(jī)科學(xué)領(lǐng)域研究和應(yīng)用的熱門領(lǐng)域,算法的改進(jìn)研究一直是一個(gè)十分困難的課題。作為字符串匹配中...
    潮汐行者閱讀 1,689評論 2 6
  • 一、字符串操作 strcpy(p, p1) 復(fù)制字符串 strncpy(p, p1, n) 復(fù)制指定長度字符串 s...
    JaiUnChat閱讀 1,676評論 0 7
  • 9.19--9.23 第7章 正則表達(dá)式 正則表達(dá)式是一個(gè)拆分字符串并查詢相關(guān)信息的過程。 推薦練習(xí)網(wǎng)站: js ...
    如201608閱讀 1,071評論 0 4
  • 有感。愛情的開始并不是兩個(gè)人多么多么相配,最好的愛情,是一起慢慢地走過,一起進(jìn)步,一起成熟
    88497ef8823d閱讀 122評論 0 0