Codeforces985F

题目链接:http://codeforces.com/contest/985/problem/F

题意:取出字符串Str里的两个串S,T,问对应位置的的字符在否有一一映射关系。

思路:
字符串hash

对于每一个字母单独hash

对于一段区间,求出每个字母的hash值,然后排序,如果能匹配上,就说明在这段区间存在字母间的一一映射,可以借助2进制01进行考虑。

题解:

#include <bits/stdc++.h>

using namespace std;
const int maxn = 2e5 + 7;
using ll = long long ;
struct HS
{
    int n;
    char s[maxn];
    ll base[2][maxn];
    ll seed[2] = {31LL, 131LL};
    ll mod[2]  = {987654321LL, 1000000007LL};
    ll Hash[2][26][maxn];

    void init() {
        n = strlen(s + 1);
        for(int i = 0;i < 2;i ++) {
            base[i][0] = 1;
            for(int j = 1;j <= n;j ++) base[i][j] = base[i][j-1] * seed[i] % mod[i];
        }
        for(int i = 0;i < 2;i ++) {
            for(int j = 1;j <= n;j ++) {
                for(int k = 0;k < 26;k ++) {
                    Hash[i][k][j] = ( Hash[i][k][j-1] * seed[i] + (s[j] == 'a' + k) ) % mod[i];
                }
            }
        }
    }
    ll getlr(int p, int k, int l, int r) {
        ll tmp = ( Hash[p][k][r] -  Hash[p][k][l-1] * base[p][r-l+1] );
        tmp %= mod[p];
        tmp += mod[p];
        tmp %= mod[p];
        return tmp;
    }
}hs;
ll A[2][26], B[2][26];
int main()
{
    int n, q;
    scanf("%d %d %s", &n, &q, hs.s+1);
    hs.init();
    while(q --) {
        int l1, l2, len;
        bool fg = 1;
        scanf("%d %d %d", &l1, &l2, &len);
        for(int i = 0;i < 26;i ++) {
            A[0][i] = hs.getlr(0, i, l1, l1 + len - 1);
            B[0][i] = hs.getlr(0, i, l2, l2 + len - 1);
        }
        sort(A[0], A[0] + 26);
        sort(B[0], B[0] + 26);
        for(int i = 0;i < 26;i ++) {
            if(A[0][i] != B[0][i]) {
                fg = 0;
                break;
            }
        }
        if(!fg) {
            puts("NO");
            continue;
        }
        for(int i = 0;i < 26;i ++) {
            A[1][i] = hs.getlr(1, i, l1, l1 + len - 1);
            B[1][i] = hs.getlr(1, i, l2, l2 + len - 1);
        }
        sort(A[1], A[1] + 26);
        sort(B[1], B[1] + 26);
        for(int i = 0;i < 26;i ++) {
            if(A[1][i] != B[1][i]) {
                fg = 0;
                break;
            }
        }
        puts(fg ? "YES" : "NO");
    }
    return 0;
}


发布了215 篇原创文章 · 获赞 16 · 访问量 3万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章