KMP+哈希整理

题目链接:
两道模版题:
CF471Dhttp://codeforces.com/problemset/problem/471/D
POJ3461http://poj.org/problem?id=3461

KMP模版:
kuangbin:

void get_next()
{
	Next[0]=-1;
	int i=0,j=-1;
	 while(i<wlen){ 
		 while(-1!=j && w[i]!=w[j])  j=Next[j]; 
		 Next[++i]=++j;
	 } 
}
void Searchkmp()
{
	int i=0;
	int j=0;
	while(i<slen)
   { 
	 while(-1!=j && s[i]!=w[j])j=Next[j]; 
		i++;j++; 
		if(j>=wlen){ 
		cnt++; 
		j=Next[j]; 
	    } 
	 }
}

KMP讲解1:https://www.cnblogs.com/zhangtianq/p/5839909.html
KMP讲解2:https://blog.csdn.net/f1033774377/article/details/82556438
KMP使用过程中注意模版中根据题目的细节变化

哈希讲解1:https://www.cnblogs.com/moyujiang/p/11213535.html
哈希讲解2:https://blog.csdn.net/pengwill97/article/details/80879387
哈希使用过程中一定要注意unsigned long long地方的处理(不可以小于0)

cin加快读入:ios::sync_with_stdio(false);
好几次因为多组数据cin读入导致超时。

POJ3461:

//哈希
#include<iostream>
#include<cstdio>
#include<string>
#include<vector>
#include<map>
#include<string.h>
using namespace std;
#define ll  unsigned long long
const ll mod=1e9+7;
#define p 31
char a[1000010];
char b[1000010];
ll Hash[1000010];
ll id[1000010];
ll idx;
ll Pow[100100];
ll aim;
int main()
{
	int t;
	scanf("%d",&t);
	Pow[0]=1;
	for(int i=1;i<=100050;i++)
	{
		Pow[i]=Pow[i-1]*p%mod;
	}
	while(t--)
	{
		memset(Hash,0,sizeof(Hash));
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		scanf("%s",a);
		scanf("%s",b);
	
		int len1=strlen(a);
		aim=a[0]+1-'A';
		idx=a[0]+1-'A';
		for(int i=1;i<len1;i++)
		{
			idx=a[i]+1-'A';
			aim=(aim*p+idx)%mod;
		}
		int len2=strlen(b);
		id[0]=b[0]+1-'A';
		Hash[0]=id[0];
		int ans=0;
		for(int i=1;i<len2;i++)
		{
			id[i]=b[i]+1-'A';
			Hash[i]=(Hash[i-1]*p+id[i])%mod;
		}
		for(int i=0;i+len1-1<len2;i++)
		{
			ll temp;
		    if(i==0)
				temp=Hash[len1-1]%mod;
			else
		        temp=(Hash[i+len1-1]+mod-(Hash[i-1]*Pow[len1])%mod)%mod;
			if(temp==aim)
				ans++;
		}
		printf("%d\n",ans);
	}
	return 0;
}


//KMP
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
#define maxn 1000100
int Next[maxn];
string w;
string s;
int slen,wlen;
int cnt;
void get_next()
{
	Next[0]=-1;
	int i=0,j=-1;
	/*while(i<wlen-1)
	{
		if(j==-1||w[i]==w[j])
		{
			i++;j++;
			if(w[i]==w[j])
				Next[i]=Next[j];
			else
				Next[i]=j;
		}
		else
			j=Next[j];
	}*/
	 while(i<wlen){ 
		 while(-1!=j && w[i]!=w[j])  j=Next[j]; 
		 Next[++i]=++j;
	 } 
}
void Searchkmp()
{
	int i=0;
	int j=0;
	while(i<slen)
   { 
	 while(-1!=j && s[i]!=w[j])j=Next[j]; 
		i++;j++; 
		if(j>=wlen){ 
		cnt++; 
		j=Next[j]; 
	    } 
	 }
}
int main()
{
	ios::sync_with_stdio(false);
	int t;
	cin>>t;
	while(t--)
	{
	    cin>>w;
	    cin>>s;
		slen=s.size();
		wlen=w.size();
		get_next();
		cnt=0;
		Searchkmp();
		cout<<cnt<<endl;
	}
	return 0;
}

CF471D

//哈希做法
#include<iostream>
#include<cstdio>
using namespace std;
#define p 31
#define ll unsigned long long
const int mod=1e9+7;
const int mod2=3145739;
int n,w;
int a[220000];
int b[220000];
int ha[220000];
int hb[220000];
int idx[220000];
ll Hash[220000];
ll Hash2[220000];
ll aHash,bHash;
int aidx;
ll qpow(ll a,ll n)
{
	ll res=1;
	while(n)
	{
		if(n&1) res=res*a%mod;
		a=a*a%mod;
		n>>=1;
	}
	return res;
}

int main()
{
	cin>>n>>w;
	for(int i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
		if(i>0)
		    ha[i]=a[i]-a[i-1];
	}
	for(int i=0;i<n;i++)
	{
		idx[i]=ha[i];
		if(i==0)
		{
			Hash[i]=0;
			//Hash2[i]=0;
		}
		else
		{
			Hash[i]=(ll)(Hash[i-1]*p+(idx[i]+mod))%mod;
			//Hash2[i]=(ll)(Hash2[i-1]*p+(idx[i]+mod2))%mod2;
		}
	}
	for(int i=0;i<w;i++)
	{
		scanf("%d",&b[i]);
		if(i>0)
			hb[i]=b[i]-b[i-1];
	}
	aHash=0;
	for(int i=1;i<w;i++)
	{
		aidx=hb[i];
		aHash=(ll)(aHash*p+(aidx+mod))%mod;
		//bHash=((bHash*p+mod2)+(aidx+mod2))%mod2;
	}
	int ans=0;
	ll Pow=qpow(p,w-1);
	for(int i=1;i+w-2<n;i++)
	{
		if(aHash==((Hash[i+w-2]+mod)-(Hash[i-1]*Pow)%mod)%mod)
			ans++;
	}
	cout<<ans<<endl;
	return 0;
}
//差分+KMP
			
#include<iostream>
#include<cstdio>
using namespace std;
int n,w;
int a[220000];
int b[220000];
int ha[220000];
int hb[220000];
int Next[220000];

void get_next()
{
	int j=0;
	for(int i=2;i<w;i++)
	{
		while((hb[j+1]!=hb[i])&&(j>0))
			j=Next[j];
		if(hb[j+1]==hb[i])
			j++;
		Next[i]=j;
	}
}
int KmpSearch()  
{  
	int ans=0;
    int i = 0;  
    int j = 0;  
    int aLen = n;  
    int bLen = w;  
	Next[0]=-1;
    while (i<aLen)  
    {       
        if (j == 0||ha[i]==hb[j])  
        {  
            i++;  
            j++;  
        }  
        else  
        {      
            j=Next[j-1]+1;  
        }
		if(j==bLen)
		{
			j=Next[j-1]+1;
			ans++;
		}
    }  
	return ans;
}  

int main()
{
	cin>>n>>w;
	for(int i=0;i<n;i++)
		scanf("%d",&a[i]);
	for(int i=0;i<w;i++)
		scanf("%d",&b[i]);
	hb[0]=0;
	for(int i=1;i<w;i++)
	{
		hb[i]=b[i]-b[i-1];
	}
	ha[0]=0; 
	for(int i=1;i<n;i++)
	{
		ha[i]=a[i]-a[i-1];
	}
	get_next();
	int ans=KmpSearch();
	cout<<ans<<endl;
	return 0;
}
原创文章 65 获赞 3 访问量 2112

猜你喜欢

转载自blog.csdn.net/littlegoldgold/article/details/104816059
今日推荐