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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章