字符串匹配--hash
字符串匹配--hash
思路:
先算出母串的hash值,再算出子串的hash值,利用差分的思想,计算出母串长度与子串长度相等的hash值,并进行判断,如果hash值相等,即可判断他们为相同的字符串,如果担心hash值冲突,即可加以一层判断来保证结果的准确性
时间复杂度O(n)
Code:
#include<iostream> #include<vector> #include<cmath> #include<string.h> #define ull unsigned long long//ull类型数据超过2^64自动取余 using namespace std; const int X=13331;//进制数一般为13……31 const int N=1e6+5; vector<ull> strhash;//动态定义母串hash数组 vector<ull> subhash;//动态定义子串hash数组 char str[N],sub[N]; ull x[N];//x[i]为X的i次方 int subl,strl; void hash_code(char *s)//计算母串s的hash值 { strhash[0]=s[0]; for(int i=1;i<strl;i++) { strhash[i]=strhash[i-1]*X+s[i]; } } void init()//初始化x数组 { x[0]=1; for(int i=1;i<N;i++) x[i]=x[i-1]*X; } ull gethash(int left,int right)//获取字符串l到r区间的hash值 { return left?strhash[right]-strhash[left-1]*x[right-left+1]:strhash[right]; } int main() { cin>>str>>sub; strl=strlen(str); subl=strlen(sub); getnxt(); getnxtv(); strhash.resize(strl);//开辟字符串长度的空间 subhash.resize(subl);//开辟空间 init(); hash_code(str);//计算母串str的hash值 subhash[0]=sub[0]; for(int i=1;i<subl;i++) { subhash[i]=subhash[i-1]*X+sub[i];//计算子串sub的hash值 } for(int i=0;i<strl;i++) { if(gethash(i,i+subl-1)==subhash[subl-1]) cout<<i+1<<endl;//如果子串与母串的hash值相等,则证明子串与母串相等 ,并输出该子串在母串中的位置 } return 0; }