[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;
}

版权声明:本文博客原创文章,博客,未经同意,不得转载。

时间: 2025-01-01 07:40:18

[AC自己主动机] zoj Searching the String的相关文章

ZOJ 3228 Searching the String (AC自己主动机)

题目链接:Searching the String 解析:给一个长串.给n个不同种类的短串.问分别在能重叠下或者不能重叠下短串在长串中出现的次数. 能重叠的已经是最简单的AC自己主动机模板题了. 不能重叠的记录一下每一个匹配的串的起始位置保证不重叠就可以. AC代码: #include <bits/stdc++.h> using namespace std; struct Trie{ int next[600010][26], fail[600010], deep[600010]; int r

ZOJ - 3228 Searching the String (AC自己主动机)

Description Little jay really hates to deal with string. But moondy likes it very much, and she's so mischievous that she often gives jay some dull problems related to string. And one day, moondy gave jay another problem, poor jay finally broke out a

zoj 3430 Detect the Virus(AC自己主动机)

Detect the Virus Time Limit: 2 Seconds      Memory Limit: 65536 KB One day, Nobita found that his computer is extremely slow. After several hours' work, he finally found that it was a virus that made his poor computer slow and the virus was activated

ZOJ 3494 BCD Code (AC自己主动机 + 数位DP)

题目链接:BCD Code 解析:n个病毒串.问给定区间上有多少个转换成BCD码后不包括病毒串的数. 很奇妙的题目. . 经典的 AC自己主动机 + 数位DP 的题目. 首先使用AC自己主动机,得到bcd[i][j]表示状态i,加了数字j以后到达的状态.为-1表示不能转移 然后就是数位DP了 注意记录为0的状态 AC代码: #include <cstdio> #include <iostream> #include <cstring> #include <algo

字符串算法之 AC自己主动机

近期一直在学习字符串之类的算法,感觉BF算法,尽管非常easy理解,可是easy超时,全部就想学习其它的一些字符串算法来提高一下,近期学习了一下AC自己主动机.尽管感觉有所收获,可是还是有些朦胧的感觉,在此总结一下,希望大家不吝赐教. 一.AC自己主动机的原理: Aho-Corasick automaton.该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之中的一个. 一个常见的样例就是给出N个单词,在给出一段包括m个字符的文章,让你找出有多少个单词在这文章中出现过,.要搞懂AC自己主动

【UVA】1449-Dominating Patterns(AC自己主动机)

AC自己主动机的模板题.须要注意的是,对于每一个字符串,须要利用map将它映射到一个结点上,这样才干按顺序输出结果. 14360841 1449 option=com_onlinejudge&Itemid=8&page=show_problem&problem=4195" style="font-size:13.3333330154419px; margin:0px; padding:0px; color:rgb(153,0,0); text-decoratio

HDU 2222 Keywords Search(AC自己主动机模板题)

题意:给出一个字符串和若干个模板,求出在文本串中出现的模板个数. 思路:由于有可能有反复的模板,trie树权值记录每一个模板出现的次数就可以. #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map&

hdu4758 Walk Through Squares (AC自己主动机+DP)

Walk Through Squares Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 944 Accepted Submission(s): 277 Problem Description On the beaming day of 60th anniversary of NJUST, as a military college whic

[POJ 1204]Word Puzzles(Trie树暴搜&amp;amp;AC自己主动机)

Description Word puzzles are usually simple and very entertaining for all ages. They are so entertaining that Pizza-Hut company started using table covers with word puzzles printed on them, possibly with the intent to minimise their client's percepti