Substring ProblemProblem 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;
}