栈hash(可删除):
const int maxn = 5e6 + 5;
char a[maxn], b[maxn], sta[maxn];
unsigned int hsta[maxn], jian[maxn] = {1};
int main()
{
for (int i = 1; i < maxn; ++i) jian[i] = jian[i - 1] * 31;
while (~scanf("%s %s", b, a)){
int la = strlen(a), lb = strlen(b), sp = 0;
unsigned int hans = 0;
for (int i = 0; i < lb; ++i) hans = hans * 31 + b[i];
for(int i = 0; i < la; ++i){
sta[++sp] = a[i];
hsta[sp] = hsta[sp - 1] * 31 + sta[sp];
if (sp > lb) hsta[sp] -= jian[lb] * sta[sp - lb];
if (hsta[sp] == hans) sp -= lb;
}
sta[++sp] = '\0';
puts(sta + 1);
}
return 0;
}
一维:
int main()
{
scanf("%s%*c", m + 1);
gets(s + 1);
int i, lm = strlen(m + 1) + 2, ls = strlen(s + 1) + 2;
m[0] = m[lm - 1] = s[0] = s[ls - 1] = ' ';
for (int i = 1; i < lm - 1; ++i) if (isupper(m[i])) m[i] = tolower(m[i]);
for (int i = 1; i < ls - 1; ++i) if (isupper(s[i])) s[i] = tolower(s[i]);
ull hm = 0, hs = 0, sum = 1;
for (i = 0; i < lm; ++i) sum *= h;
for (i = 0; i < lm; ++i) hm = hm * h + m[i];
for (i = 0; i < lm; ++i) hs = hs * h + s[i];
int p;
for (i = 0; i + lm <= ls; ++i){
if (hs == hm){
p = i;
break;
}
hs = hs * h - s[i] * sum + s[i + lm];
}
if (i > ls - lm) return 0 & puts("-1");
int ans = 0;
for (; i + lm <= ls; ++i){
if (hs == hm) ++ans;
hs = hs * h - s[i] * sum + s[i + lm];
}
printf("%d %d\n", ans, p);
return 0;
}
https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1347
一道二愣子题愣是被我写成了滚动hash,我也是醉了,脑子不好使了吧,那这个hash就当模板吧
我们把对串旋转几次就可以发现一个对串不管旋转多少次都是对串。
unsigned int a, b, t = 1;
int main()
{
string s;
while (cin >> s){
int ls = s.size();
if (ls & 1){
puts("NO");
continue;
}
ls /= 2;
for (int i = 0; i < ls; ++i) t *= mod;
for (int i = 0; i < ls; ++i) a = a * mod + s[i];
for (int i = ls; i < 2 * ls; ++i) b = b * mod + s[i];
s += s;
bool yes = 0;
for (int i = 0; i < ls; ++i){
if (a == b){
yes = 1;
puts("YES");
break;
}
a += - t * s[i] + s[i + ls];
b += - t * s[i + ls] + s[i + 2 * ls];
}
if (!yes) puts("NO");
}
return 0;
}
二维:BZOJ – 矩阵模板
https://cn.vjudge.net/contest/243932#problem/O
原来unsigned int和unsigned long long都会自然溢出,但是unsigned long long会TLE,再也不用这个了。
另外,原来还可以直接对结果hash存表然后O(1)查找,太厉害了啊。
woc刚才把p = 99999971改成1000007直接快了一秒,还是恐怖啊,应该就是越接近10的倍数处理的越快。
各种优化之后从1800ms降到了500ms。
#include<bits/stdc++.h>
#define maxn 1005
using namespace std;
typedef unsigned int ui;
const ui b1 = 31, b2 = 107, p = 1000007;
char g[maxn][maxn];
ui res[maxn][maxn], p1 = 1, p2 = 1;
int n, m, a, b, q;
bool hashp[p];
void init_hash()
{
for (int i = 0; i < n; ++i){
ui e = 0;
for (int j = 0; j < b; ++j)
e = e * b1 + g[i][j];
for (int j = 0; j + b < m; ++j){
res[i][j] = e;
e = e * b1 - p1 * g[i][j] + g[i][j + b];
}
res[i][m - b] = e;
}
for (int j = 0; j + b <= m; ++j){
ui e = 0;
for (int i = 0; i < a; ++i)
e = e * b2 + res[i][j];
for (int i = 0; i + a < n; ++i){
hashp[e % p] = 1;
e = e * b2 - p2 * res[i][j] + res[i + a][j];
}
hashp[e % p] = 1;
}
}
ui c_hash()
{
ui e2 = 0, e1 = 0;
for (int i = 0; i < a; ++i, e1 = 0){
for (int j = 0; j < b; ++j){
e1 = e1 * b1 + g[i][j];
}
e2 = e2 * b2 + e1;
}
return e2;
}
int main()
{
scanf("%d %d %d %d", &n, &m, &a, &b);
for (int i = 0; i < b; ++i) p1 *= b1, p2 *= b2;
for (int i = 0; i < n; ++i) scanf("%s", g[i]);
init_hash();
scanf("%d", &q);
while (q--){
for (int i = 0; i < a; ++i) scanf("%s", g[i]);
if (hashp[c_hash() % p]) puts("1");
else puts("0");
}
return 0;
}