题目链接: 救救企鹅
一、题目描述
另一天,一只可爱的围着围巾的肥企鹅在路上摇摇晃晃地走着,遇上了迎面走来的打着饱嗝的PM6。小企鹅预感不妙,这不就是最近有名的恶人PM6么!吓得立刻扭头就想跑。
PM6:“小火汁,站住!我不吃你(谁叫你是保护动物)。我这有一道简单题,如果你答对了,我就给你吃鱼肉,如果你答错了,就免费帮我充游戏币!”
企鹅:“(:3J∠)(默默摘掉围巾)”
PM6:“我给你一个文本串 S ,再给你两个串A、B,你要将文本串中的 A 都转换成 B ,转换后的字符不再参与转换,输出最终的文本串。”
求求你救救企鹅
二、输入描述:
- 第一行输入一个文本串 S 。
- 第二行输入字符串 A 。
- 第三行输入字符串 B 。
- S|为S的长度,|A|为A的长度,|B|为B的长度,所有字符都是小写字母,保证 |A| <= |S| 。
- 对于50%的数据:1<= |A|、|B|、|S| <=1000
- 对于100%的数据:1<= |A|、|B|、|S| <=1000000
三、输出描述:
只有一行,输出转换后的文本串。
示例1:
- 输入
abababcd
ab
cd - 输出
cdcdcdcd
四、思路
- 显然题意是求 在s串中 将所有a串替换成c串,同时s,a,b串的长度均<=1e6, 暴力求解很可能会TLE;
- 自然就想到KMP算法,找出a串的next数组,然后对s串进行匹配,将完全匹配处的首字符的下标用map进行维护,最后得到一个存有s串中所有完全匹配a串的位置的map;
- 输出时如果当前位置的map值为1,则输出b串,同时将指针后移|a|位,最终全部输出;
六、Code
#include <bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
#define ll long long
const int Max = 1e6+3;
const int mod = 1e9+7;
char s[Max], a[Max], b[Max];
int slen, alen, blen, next[Max];
map<int, int> mp;
void GetNext()
{
next[0]=-1;
int k=-1;
int j=0;
while(j<=alen-1){
if(k==-1||a[j]==a[k]){
k++;
j++;
next[j]=k;
}
else k=next[k];
}
}
void FindStr()
{
int i=0,j=0;
while(i<slen)
{
if(j==-1||s[i]==a[j])
{
if(j==alen-1)
{
mp[i-j] = 1;
j=next[j];
}
j++;
i++;
}else j=next[j];
}
}
int main()
{
scanf("%s%s%s", s, a, b);
slen = strlen(s);
alen = strlen(a);
blen = strlen(b);
GetNext();
FindStr();
for(int i=0; i<slen; i++)
{
if(mp[i]) {
for(int j=0; j<blen; j++)
printf("%c", b[j]);
i = i + alen - 1;
}
else printf("%c", s[i]);
}
return 0;
}
蒟蒻一只,欢迎指正