1. 程式人生 > >字串hash(scu4438)

字串hash(scu4438)

Censor

frog is now a editor to censor so-called sensitive words (敏感詞).

She has a long text pp. Her job is relatively simple -- just to find the first occurence of sensitive word ww and remove it.

frog repeats over and over again. Help her do the tedious work.

Input

The input consists of multiple tests. For each test:

The first line contains 11 string ww. The second line contains 11 string pp.

(1≤length of w,p≤5⋅1061≤length of w,p≤5⋅106, w,pw,p consists of only lowercase letter)

Output

For each test, write 11 string which denotes the censored text.

Sample Input

    abc
    aaabcbc
    b
    bbb
    abc
    ab

Sample Output

    a
    
    ab

字串hash可以解決這道題在這裡推薦一個部落格可以很好的瞭解字串hash的集中模式和其安全係數。在這裡直接上程式碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define pi acos(-1)
#define e exp(1)
#define For(i, a, b) for(int (i) = (a); (i) <= (b); (i) ++)
#define Bor(i, a, b) for(int (i) = (b); (i) >= (a); (i) --)
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define eps 1e-7
using namespace std;
typedef long long ll;
const int maxn = 5e6 + 10;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-10;
const ll Hash = 1e7 + 9;
const ll mode = 1e9 + 7;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
inline int read(){
    int ret=0,f=0;char ch=getchar();
    while(ch>'9'||ch<'0') f^=ch=='-',ch=getchar();
    while(ch<='9'&&ch>='0') ret=ret*10+ch-'0',ch=getchar();
    return f?-ret:ret;
}
char strA[maxn],strB[maxn];
char tmp[maxn];
ll hb[maxn];
ll preHash[maxn];
void presolve(){
	preHash[0] = 1;
	for(int i = 1; i < maxn; i++){
		preHash[i] = preHash[i - 1] * Hash % mode; 
	}
}
int main(){
	//ios::sync_with_stdio(false);
	presolve();
	while(~scanf("%s%s",strA,strB)){
		int lena = strlen(strA);
		int lenb = strlen(strB);
		ll ha = 0, top = 0;
		if(lena > lenb){
			printf("%s\n",strB);
			continue;
		}
		hb[0] = 0;
		for(int i = 0; i < lena; i++)ha = ((ha*Hash%mode) + strA[i]-'a'+1)%mode;
		for(int i =0; i < lenb; i++){
			tmp[top++] = strB[i];
			hb[top] = ((hb[top-1]*Hash%mode) + strB[i]-'a'+1) % mode;
			if(top >= lena && (((hb[top] - hb[top-lena]*preHash[lena])%mode + mode)%mode==ha)){
				top -= lena;
			}
		}
		for(int i = 0; i < top; i++){
			cout << tmp[i];
		}cout << endl;
	}
	return 0;
}

使用ull來做的程式碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define pi acos(-1)
#define For(i, a, b) for(int (i) = (a); (i) <= (b); (i) ++)
#define Bor(i, a, b) for(int (i) = (b); (i) >= (a); (i) --)
using namespace std;
typedef long long ll;
const int maxn = 5e6 + 10;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-10;
const ll mod = 1e9 + 7;
inline int read(){
    int ret=0,f=0;char ch=getchar();
    while(ch>'9'||ch<'0') f^=ch=='-',ch=getchar();
    while(ch<='9'&&ch>='0') ret=ret*10+ch-'0',ch=getchar();
    return f?-ret:ret;
}

char str[maxn],s[maxn]; 
const ll Hash = 1e5 +7;
int n,m;
ll multi[maxn];
ll Stack[maxn], Hash_str;
char ans[maxn];

inline bool check(int pos){
	if(pos >= n){
		if(Stack[pos] - Stack[pos - n] * multi[n] == Hash_str)
			return true;
	}
	return false;
}

void init(){
	multi[0] = 1;
	for(int i = 1; i < maxn; i++){
		multi[i] = multi[i-1] * Hash;
	}
}

int main(){
	init();
	while(~scanf("%s%s",str,s)){
		n = strlen(str);
		m = strlen(s);
		Hash_str = 0;
		for(int i = 0; i < n; i++){
			Hash_str = Hash_str * Hash + *(str + i);
		}
		Stack[0] = 0;
		int top = 0;
		for(int i = 0; i < m; i ++){
			ans[top++] = s[i];
			Stack[top] = Stack[top - 1] * Hash + *(s + i);
			if(check(top)) top -= n;
		}
		for(int i = 0; i < top; i++)
			printf("%c",ans[i]);
		puts("");
	}
	
	return 0;
}

繼續努力加油: