알고리즘/백준

[백준/BOJ/1786] 찾기

코딩하는 회사원 2024. 1. 13. 15:01
728x90

원래 정석의 라빈카프로 접근해야 했다면 hash 값이 똑같을 때, 하나씩 문자 비교하는 작업이 필요하다.

그러나 hash 함수를 매우 잘 짜면 기도메타 방법으로 문자 비교하지 않고 index 만 저장하는 방식으로 해결 가능하다.

 

1번 코드는 정석 방법 (35% 에서 시간 초과)

2번 코드는 기도메타 방법 (통과)

3번 코드는 해시를 2개 쓰는 방법이다. 확률 변수가 하나 더 추가 되기 때문에 이 방법이 정 해 일 가능성이 높다.

#include <iostream>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
const ll MOD = (1L << 31) -1;
const int MAX = 1e6+1;
//char S[MAX],W[MAX];
string S,W;
inline ll __mod(ll n){
	if(n>=0) return n%MOD;
	return ((-n/MOD+1)*MOD+n)%MOD;
}
int main(){	
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	//gets(S);
	//gets(W);
	
	std::getline(std::cin,S);
	std::getline(std::cin,W);
	ll N = S.size();
	ll M = W.size();
	ll SH = 0;
	ll WG = 0;
	ll power = 1;
	ll res = 0;
	vector<int> v;
	for(int i=0;i<=N-M;i++){
		if(i==0){
			for(int j=0;j<M;j++){
				WG = __mod(WG+1LL*W[M-1-j]*power);
				SH = __mod(SH+1LL*S[M-1-j]*power);
				if(j<M-1) power=__mod(power*7);
			}
		}
		else{
			SH = __mod(7*(SH-1LL*S[i-1]*power))+S[i+M-1];
		}
		if(WG==SH){
			bool flag=true;
			for(int j=0;j<M;j++){
				if(S[i+j] != W[j]){
					flag=false;
					break;
				}
			}
			if(flag) {
				v.push_back(i+1);
			}
		}
	}
	cout<<v.size()<<"\n";
	for(int i=0;i<v.size();i++){
		cout<<v[i]<<" ";
	}
	return 0;
}

 

#include <iostream>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
const ll MOD = 1e9+7;
const int MAX = 1e6+1;
//char S[MAX],W[MAX];
string S,W;
inline ll __mod(ll n){
	if(n>=0) return n%MOD;
	return ((-n/MOD+1)*MOD+n)%MOD;
}
int main(){	
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	//gets(S);
	//gets(W);
	
	std::getline(std::cin,S);
	std::getline(std::cin,W);
	ll N = S.size();
	ll M = W.size();
	ll SH = 0;
	ll WG = 0;
	ll power = 1;
	ll res = 0;
	vector<int> v;
	for(int i=0;i<=N-M;i++){
		if(i==0){
			for(int j=0;j<M;j++){
				WG = __mod(WG+1LL*W[M-1-j]*power);
				SH = __mod(SH+1LL*S[M-1-j]*power);
				if(j<M-1) power=__mod(power*31);
			}
		}
		else{
			SH = __mod(31*(SH-1LL*S[i-1]*power))+S[i+M-1];
		}
		if(WG==SH){
			v.push_back(i+1);
		}
	}
	cout<<v.size()<<"\n";
	for(int i=0;i<v.size();i++){
		cout<<v[i]<<" ";
	}
	return 0;
}
#include <iostream>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
const int MOD = 1e9 + 7;
const int MAX = 1e6 + 1;
string T, P;
vector<int> loc;
ll __mod(ll a) {
	if (a >= 0) return a % MOD;
	return ((-a / MOD + 1)*MOD + a) % MOD;
}
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	std::getline(std::cin, T);
	std::getline(std::cin, P);
	int N = T.size();
	int M = P.size();
	ll th1 = 0, th2 = 0;
	ll ph1 = 0, ph2 = 0;
	ll pwr1 = 1, pwr2 = 1;
	for (int i = 0; i <= N-M; i++) {
		if (i == 0) {
			for (int j = 0; j < M; j++) {
				th1 = __mod(th1 + 1LL * pwr1*T[M-1-j]);
				ph1 = __mod(ph1 + 1LL * pwr1*P[M - 1 - j]);
				th2 = __mod(th2 + 1LL * pwr2*T[M-1-j]);				
				ph2 = __mod(ph2 + 1LL * pwr2*P[M-1-j]);
				if (j < M - 1) {
					pwr1 = __mod(pwr1 * 3);
					pwr2 = __mod(pwr2 * 7);
				}
			}
		}
		else {
			th1 = __mod(3 * (th1 - 1LL * pwr1*T[i - 1]) + T[i+M-1]);
			th2 = __mod(7 * (th2 - 1LL * pwr2*T[i - 1]) + T[i+M-1]);
		}
		if (th1 == ph1 && th2 == ph2) {
			loc.push_back(i+1);
		}		
	}
	cout << loc.size() << "\n";
	for (auto idx : loc) {
		cout << idx << " ";
	}
	cout << "\n";
	return 0;
}
728x90