转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
题意:给了一个母串,然后有多个匹配串,问在母串中是否能找到不重叠两个子串,拼接成匹配串
http://codeforces.com/problemset/problem/149/E
我的做法是,对于每一个匹配串
正向KMP一次,记录对于匹配串的每一个长度在模式串能匹配的最左边,也就是首次匹配的位置
然后将母串和匹配串都反向,再KMP一次
然后枚举长度 ,判断是否有重叠
感觉还是不错的题,主要是KMP现在都不会了,SAD...
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#include<set>
#include<string>
#include<queue>
#define inf 1600005
#define M 40
#define N 100005
#define maxn 300005
#define eps 1e-12
#define zero(a) fabs(a)<eps
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define pb(a) push_back(a)
#define mp(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long
#define MOD 1000000007
#define lson step<<1
#define rson step<<1|1
#define sqr(a) ((a)*(a))
#define Key_value ch[ch[root][1]][0]
#define test puts("OK");
#define pi acos(-1.0)
#define lowbit(x) ((-(x))&(x))
#define HASH 1331
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
int next[1005];
char str[100005],str_2[100005],pat[1005];
int m;
int l[1005],r[1005];
void get_next(char *s,int len){
next[0]=-1;
int i=0,j=-1;
while(i<len){
if(j==-1||s[i]==s[j]){
i++;j++;
if(s[i]==s[j]) next[i]=next[j];
else next[i]=j;
}
else j=next[j];
}
}
void match(char *pat,int lp,char *str,int ls,int *dp){
int i=0,j=0;
while(i<lp&&j<ls){
if(i==-1||pat[i]==str[j]){
i++;j++;
dp[i]=min(dp[i],j);
}
else i=next[i];
if(i==lp) i=next[i];
}
}
void Init(int len){
l[0]=r[0]=0;
for(int i=1;i<=len;i++){
l[i]=inf;
r[i]=inf;
}
}
int main(){
//freopen("input.txt","r",stdin);
while(scanf("%s",str)!=EOF){
int cnt=0,length=strlen(str);
for(int i=0;i<length;i++)
str_2[i]=str[length-1-i];
scanf("%d",&m);
while(m--){
scanf("%s",pat);
int len=strlen(pat);
if(len==1) continue;
Init(len);
get_next(pat,len);
match(pat,len,str,length,l);
for(int i=0;i<len/2;i++){
swap(pat[i],pat[len-i-1]);
}
get_next(pat,len);
match(pat,len,str_2,length,r);
for(int i=1;i<=len;i++){
//cout<<i<<" "<<l[i]<<" "<<r[len-i]<<endl;
if(l[i]+r[len-i]<=length){
cnt++;
break;
}
}
}
printf("%d\n",cnt);
}
return 0;
}