救救企鹅
题目描述:
另一天,一只可爱的围着围巾的肥企鹅在路上摇摇晃晃地走着,遇上了迎面走来的打着饱嗝的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
其实基本上就是个字符串hash水题,当然也可以用kmp及其他算法解决。写完hash后发现了其他两个骚操作,记录一下。
Code1:字符串hash (23ms)
#include<iostream>
#include<cstring>
using namespace std;
typedef unsigned long long ULL;
const int N = 1e6+7 , P = 131;
int n,m;
char str[N],a[N],b[N];
ULL h[N],p[N],h2[N]; //C++中溢出相当于取模;
bool vis[N];
ULL get_hash(int l,int r){ //l~r 区间hash值
return h[r] - h[l-1] * p[r - l + 1];
}
int main()
{
scanf("%s%s%s",str+1,a+1,b+1);
p[0] = 1;
int n = strlen(str+1),m = strlen(a+1);
for(int i=1;i<=n;i++){
h[i] = h[i-1] * P + str[i]; //预处理1~i子串的hash值;
p[i] = p[i-1] * P;
}
for(int i=1;i<=m;i++) h2[i] = h2[i-1]*P + a[i];
ULL cnt = h2[m];
int pos = m;
while(pos<=n){
if(get_hash(pos-m+1,pos)==cnt) {
vis[pos-m+1] = 1;
pos += m;
}else pos++;
}
pos = 1;
while(pos<=n){
if(vis[pos]){
printf("%s",b+1);
pos += m;
}else printf("%c",str[pos]),pos++;
} printf("\n");
return 0;
}
以下两种写法貌似只比hash慢一倍?但是试了一下substr就会超时 QWQ 学到了
Code2:(50ms)
#include <bits/stdc++.h>
using namespace std;
string s,a,b;
int main(){
cin>>s>>a>>b;
while(1){
int pos=s.find(a);
if(pos==-1) break;
s.erase(pos,a.size());
s.insert(pos,b);
}
cout<<s;
return 0;
}
Code3: (51ms)
#include <bits/stdc++.h>
using namespace std;
int main() {
string s,a,b;
cin >> s >> a >> b;
int c;
while((c=s.find(a))!=-1) {
s.replace(c,a.size(),b);
}
cout<<s;
}