Substring Problem+SPOJ+AC自动机

 Substring Problem

Problem code: SUB_PROB


String Matching is an important problem in computer science research and finds applications in Bioinformatics, Data mining,pattern recognition, Internet security and many more areas.

The problem we consider here is a smaller version of it. You are given a string M and N other strings smaller in length than M. You have to find whether each of these N strings is a substring of M. All strings consist of only alphanumeric characters.

You are required to write a C/CPP code to solve the problem.

Input

Input to the program consists of a series of lines. The first line contains the string M (no more than 100000characters long). The next line contains an integer N (<1000) the number of query strings. Each of the next N lines contain a string S (each of which is no more than 2000 characters long).

Output

Output should consist of N lines each with a character 'Y'/'N' indicating whether the string S is a substring of String M or not.

Example

Input:
abghABCDE
2
abAB
ab


Output:
 
N
Y

Note: The test data for this problem not only consist of the official test cases from the contest,as well some cases of my own.

解决方案:一道很裸的AC自动机,可能有多个相同的模式串,所以可以咯一个vector容器来维护多个相同模式串出现的情况。

code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#define Max 100005
using namespace std;
char text[Max];
bool exits[1003];
int ans;
struct trie
{
    struct trie *child[100];
    struct trie *fail;
    vector<int>v;
    trie()
    {
        for(int i=0; i<100; i++)
        {
            child[i]=NULL;
        }
        fail=NULL;
        v.clear();
    }///初始化字典树

};///定义一棵字典树
trie *root;
void Insert(char *word,int k)
{
    trie *p=root;
    int i=0;
    while(word[i]!='\0')
    {

        int c=word[i]-32;
        if(p->child[c]==NULL)
        {
            p->child[c]=new trie();
        }
        p=p->child[c];
        i++;
    }
    p->v.push_back(k);
    // cout<<k<<endl;
}///构造插入函数
void make_fail()
{
    queue<trie* >Q;
    Q.push(root);
    while(!Q.empty())
    {
        trie *p=Q.front();
        Q.pop();
        for(int i=0; i<100; i++)
        {
            if(p->child[i]!=NULL)
            {
                if(p==root) p->child[i]->fail=root;
                else
                {
                    trie *temp=p;
                    while(temp->fail!=NULL)
                    {
                        if(temp->fail->child[i]!=NULL)
                        {
                            p->child[i]->fail=temp->fail->child[i];
                            break;
                        }
                        temp=temp->fail;
                    }
                    if(temp->fail==NULL)
                    {
                        p->child[i]->fail=root;
                    }
                }
                Q.push(p->child[i]);
            }
        }



    }


}///构造fail指针函数
void ac_search()
{

    int i=0;
    trie *p=root;
    while(text[i]!='\0')
    {
        int c=text[i]-32;
        while(p!=root&&p->child[c]==NULL) p=p->fail;///若查不到这沿失败指针寻找
        if(p->child[c]!=NULL)
        {
            p=p->child[c];
            p=(p==NULL)?root:p;
            trie *temp=p;
            while(temp!=root&&temp->v.size()!=0)
            {
                ans++;
                int len=temp->v.size();
                for(int i=0;i<len;i++){
                   exits[temp->v[i]]=true;
                }
                temp=temp->fail;
            }

        }
        i++;
    }


}
int main()
{
    int N,M;
    char word[2200];
    while(~scanf("%s",text))
    {
       // cout<<text<<endl;
        scanf("%d",&N);
        root=new trie();
        for(int i=0; i<N; i++)
        {
          //  getchar();
            scanf("%s",word);
          //  cout<<word<<endl;
            Insert(word,i+1);
        }
        make_fail();
        memset(exits,false,sizeof(exits));
        ac_search();
        for(int i=1;i<=N;i++){
            if(exits[i]){
                printf("Y\n");
            }
            else printf("N\n");
        }

    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值