Description
给定一些短串,要求你在一个长串中,将这些短串部分变为(*)
Input
第一行包括一个整数(n),表示短串的数量.
接下来的(n)行,为(n)个短串.
最后一行,为你需要变化的长串.
Output
一行,表示变化后的长串.
PS:长串会有中有各种字符,短串仅包含英文字符
样例输入
3
int
ing
kitty
Int is interesting! ~OwO~
样例输出
(***) is (***)erest(***)ing! ~OwO~
上面的一些输入输出中为全角,实际上为半角.
这题做法有很多啊,可以哈希,可以AC自动机,可以KMP.
这里讲一下KMP算法.
做法为(KMP+)差分.
首先需要将长串中的字母全部转为小写(大写).
(isalpha)吼啊
我们对每一个短串求出其(next)数组.再枚举这些串去和长串匹配.
但是一些位置会出问题.
比如
给定两个短串为(GRE)和(eat),长串为(Great)
则我们的长串要变成(*****)
因此引入了差分.
如果匹配上之后,我们直接对其左端点和右端点(+1)差分。
最终枚举的话,直接判断有无标记,如果有,则将当前位置变为(*)
然后直接输出即可.
代码
#include<cstdio>
#include<cctype>
#include<cstring>
#define R register
using namespace std;
char sta[150008],stb[150008];
int pos[150008],k,n,len;
struct cod
{
int nex[55],len;
char s[55];
}str[55];
char st[55],c;
inline char ch(char s)
{
if(!isalpha(s))return s;
if(s<='Z' and s>='A')s=s-'A'+'a';
return s;
}
int main()
{
scanf("%d",&n);
for(R int i=1;i<=n;i++)
{
scanf("%s",st+1);
str[i].len=strlen(st+1);
for(R int j=1;j<=str[i].len;j++)
str[i].s[j]=ch(st[j]);
str[i].nex[1]=0;k=0;
for(R int j=2;j<=str[i].len;j++)
{
while(str[i].s[k+1]!=str[i].s[j] and k)k=str[i].nex[k];
if(str[i].s[k+1]==str[i].s[j])k++;
str[i].nex[j]=k;
}
}
getchar();
while(c!='
')
{
c=getchar();
if(c=='
')break;
sta[++len]=c;
stb[len]=ch(c);
}
for(R int i=1;i<=n;i++)
{
k=0;
for(R int j=1;j<=len;j++)
{
while(k and str[i].s[k+1]!=stb[j])k=str[i].nex[k];
if(str[i].s[k+1]==stb[j])k++;
if(k==str[i].len)
{
pos[j-str[i].len+1]++;
pos[j+1]--;
}
}
}
for(R int i=1;i<=len;i++)
{
pos[i]+=pos[i-1];
if(pos[i])sta[i]='*';
printf("%c",sta[i]);
}
}
/*
2
GRE
eat
Great Britain
***** Britain
*/