本来准备学习Hash的,结果看PPT讲的第一个算法竟然是跟字符串处理相关的,本来Hash中也有一块专门讲字符串Hash的,就按照《算法导论》中的分类,把这个分到“字符串处理”中去吧!
Rabin-Karp算法的思想超级简单:把有d个不同字母的字符串转化为一个d进制数。如果得到的这个数字太多可以模一个质数,但这样要进行一些额外的判断,因为可能有多个字串的数值会相同,这时可以用朴素算法判断(就是一对一进行比较)。(摘自:
http://skyhacker.ixiezi.com/2010/12/20/poj1200-crazysearchrabin-karp/)
对于POJ上面的那道题目就简单了!
- #include<stdio.h>
- #include<string.h>
- /*
- * Rabin-Karp算法的核心思想:把一个含NC个不同字母的字符串 转化为NC进制的数
- * */
- #define MM 16000005
- char s[MM];
- int hash[MM];
- int asc[128];
- //把NC进制的数转化为10进制的数
- int n,nc;
- void init(){
- memset(asc,0,sizeof(asc));
- memset(hash,0,sizeof(hash));
- }
- //把NC进制的数 转化成10进制的数
- void solve(){
- int ans=0;
- int len=strlen(s);
- //按照字符出现的先后顺序确定字符的大小
- for(int i=0,j=0;i<len;i++){
- if(!asc[s[i]])asc[s[i]]=j++;
- if(j==nc)break;
- }
- //把子串映射到hash中去
- int key;
- for(int i=0;i<len-n+1;i++){
- key=0;
- for(int j=i;j<i+n;j++)key+=key*nc+asc[s[j]];
- if(!hash[key])hash[key]=1,ans++;
- }
- printf("%d\n",ans);
- }
- int main(){
- scanf("%d %d",&n,&nc);
- scanf("%s",s);
- init();
- solve();
- }
参考文档: