rolling hash

也是需要查看,然后修改,rolling hash, recursive hash, polynomial hash, double hash.如果一次不够,那就2次。需要在准备一个线段树,基本的线段树容易些,带lazy标记的区间修改的线段树不是很好写。hash seed key根据需要选择, 我看别人写的,可以写成一个随机数,每次随机选择一个素数作为种子,这样好像好一些。

 1 #include<bits/stdc++.h>
 2 #define pb push_back
 3 #define FOR(i, n) for (int i = 0; i < (int)n; ++i)
 4 #define dbg(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl
 5 typedef long long ll;
 6 using namespace std;
 7 typedef pair<int, int> pii;
 8 const int maxn = 1e6 + 10;
 9 const int mod1 = 1e9 + 7;
10 const int mod2 = 1e9 + 9;
11 const int arg1 = 841;
12 const int arg2 = 151;
13 int n, k;
14 string str;
15 pii H[maxn];
16 map<pii, int> has[maxn];
17 map<pii, int> g;
18 int pw1, pw2;
19 bool check(map<pii, int> & m) {
20     for (auto it = m.begin(); it != m.end(); it++) {
21         if(it->second > 1) return 0;
22         else if(g.find(it->first) == g.end()) return false;
23     }
24     return 1;
25 }
26 void solve() {
27     cin >> n >> k;
28     cin >> str;
29     pw1 = pw2 = 1;
30     for (int i = 0; i < k - 1; i++) {
31         pw1 = ll(pw1) * arg1 % mod1;
32         pw2 = ll(pw2) * arg2 % mod2;
33     }
34     pii h = pii(0, 0);
35     for (int i = 0; i < k; i++) {
36         h.first = (ll(h.first) * arg1 + ll(str[i] - 'a' + 1)) % mod1;
37         h.second = (ll(h.second) * arg2 + ll(str[i] - 'a' + 1)) % mod2;
38     }
39     H[0] = h;
40     has[0][h]++;
41     for (int i = 1; i < n * k; i++) {
42         h.first = (ll(h.first) - ll(str[i - 1] - 'a' + 1) * pw1 % mod1 + mod1) % mod1;
43         h.second = (ll(h.second) - ll(str[i - 1] - 'a' + 1) * pw2 % mod2 + mod2) % mod2;
44         int ni = (i + k - 1) % (n * k);
45         h.first = (ll(h.first) * arg1 + ll(str[ni] - 'a' + 1)) % mod1;
46         h.second = (ll(h.second) * arg2 + ll(str[ni] - 'a' + 1)) % mod2;
47         has[i % k][h]++;
48         H[i] = h;
49     }
50     int m; cin >> m;
51     string cur;
52     for (int j = 1; j <= m; j++) {
53         cin >> cur;
54         pii h = pii(0, 0);
55         for (int i = 0; i < k; i++) {
56             h.first =  (ll(h.first) * arg1 + ll(cur[i] - 'a' + 1)) % mod1;
57             h.second = (ll(h.second) * arg2 + ll(cur[i] - 'a' + 1)) % mod2;
58             g[h] = j;
59         }
60     }
61     for (int j = 0; j < k; j++) if(check(has[j])) {
62         cout << "YES" << endl;
63         bool f = 0;
64         for (int i = j; i < n * k; i += k) {
65             if(f) cout << " ";
66             cout << g[H[i]]; f = 1;
67         }
68         cout << endl;
69         return;
70     }
71     cout << "NO" << endl;
72 }
73 int main() {
74     //freopen("test.in", "r", stdin);
75     //freopen("test.out", "w", stdout);
76     solve();
77     return 0;
78 }

 

转载于:https://www.cnblogs.com/y119777/p/6003024.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值