E:martian strings
题目大意:这题主要的想法就是给一个m,输入m个字符串,在主串中是否能找到与两个的子串使其匹配。
1.思路一:刚一开始,我用队列写的
附上代码`
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<map>
#include<algorithm>
using namespace std;
bool visited[10000];
int main()
{
string s;
cin>>s;
int sum=0;
int m;
cin>>m;
string k;
for(int i=0;i<m;i++)
{queue<char>st;
for(int c=0;c<s.size();c++)
{
st.push(s[c]);
}
int flag=0;
cin>>k;
for(int j=0;j<k.size();j++)
{
// cout<<k[j];
char t=st.front();
while(t!=k[j]&&!st.empty())
{
st.pop();
t=st.front();
}
if(t==k[j])
{
flag++;
// cout<<"增加啦"<<flag<<"t"<<t<<" "<<k[j]<<endl;
st.pop();
}
}
if(flag==k.size())
{
sum++;;;;;
// cout<<"flag"<<flag<<"k:"<<k.size();
}
}
cout<<sum<<endl;
}
但是这段代码超时了。
2.后缀自动机
但是我没改出来bug//GG
3.kmp(属实没想到怎么做)
看了几位大神的博客时候发现是正反各用一次kmp
正用kmp就是看某一段字符串能够匹配到几位,记录匹配到的位置为K,反用kmp就是将两端字符串全部改成相反的,然后进行匹配,记录匹配到的位置为T;
如果k-t>=0的话,就证明两端字符串将其完全覆盖,因此就满足题目意思。
需要解决的问题
1.如何标记K,T;
2.如何将字符串改成相反的。
附上代码:
`#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<map>
#include<algorithm>
using namespace std;
int next[10000];
string s,c;
void get_next()
{
int i=0;int j=-1;
next[0]=-1;
while(i<s.size())
{
if(j==-1||s[i]==s[j])
{
next[++i]=++j;
}
else
j=next[j];
}
}
int kmp()
{
int flag;
int i=-1,j=0;
get_next();
while(i<s.size()&&j<c.size())
{
if(i==-1||s[i]==c[j])
{
i++;
j++;
flag=i;
}
else
i==next[i];
}
return flag;
}
int kmp2()
{
int flag;
int i=s.size()-1,j=c.size()-1;
get_next();
while(i>=0&&j>=0)
{
if(s[i]==c[j])
{
i--;
j--;
flag=i;
}
else
i==next[i];
}
return flag;
}
int main()
{
cin>>c;
int m;
cin>>m;
int sum=0;
while(m--)
{
cin>>s;
int k=kmp();
int t=kmp2();
if(k+s.size()-t>=s.size())
{
sum++;
}
}
cout<<sum<<endl;
}