题目:http://poj.org/problem?id=1200
题意:给一个字符串,给定n和nc,字符串里最多有nc个不同的字符,问长度为n的不同子串最多有几个
和上一篇现场赛那个一样,也是难在判重处理不好会超时
方法:将长度为n的子串映射为一个nc进制的数,开一个大数组,判断是否重复
#include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <iostream> #include <cmath> #include <map> #include <map> #include <queue> using namespace std; #define ls(rt) rt*2 #define rs(rt) rt*2+1 #define ll long long #define ull unsigned long long #define rep(i,s,e) for(int i=s;i<e;i++) #define repe(i,s,e) for(int i=s;i<=e;i++) #define CL(a,b) memset(a,b,sizeof(a)) #define IN(s) freopen(s,"r",stdin) #define OUT(s) freopen(s,"w",stdin) const int MAXN = 16000000+100; bool Hash[MAXN]; char str[MAXN]; int m[1001]; int n,nc; int ah,base;/// int main() { //IN("poj1200.txt"); int ans,len,seed; while(~scanf("%d%d",&n,&nc)) { CL(Hash,0);CL(m,0); ah=0;ans=0;seed=0; scanf("%s",str); len=strlen(str); if(len<n){puts("0");continue;} rep(i,0,len) { if(!m[str[i]])m[str[i]]=++seed; if(seed == nc)break; } ah=m[str[0]],base=nc; for(int i=1;i<n;i++) { ah=ah*nc+m[str[i]]; base*=nc; } Hash[ah]=1;ans++; rep(i,n,len) { ah=ah*nc-m[str[i-n]]*base+m[str[i]]; if(!Hash[ah]) { Hash[ah]=1; ans++; } } printf("%d\n",ans); } return 0; }
poj 1200 --- 不错的字符串HASH构造方法
时间: 2024-10-08 15:16:39