救救企鹅(字符串hash)

救救企鹅

题目描述:
另一天,一只可爱的围着围巾的肥企鹅在路上摇摇晃晃地走着,遇上了迎面走来的打着饱嗝的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;
}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 我行我“速” 设计师:Amelia_0503 返回首页