zoukankan      html  css  js  c++  java
  • cf244D. Match & Catch 字符串hash (模板)或 后缀数组。。。


    D. Match & Catch

    能够用各种方法做。字符串hash。后缀数组,dp。拓展kmp,字典树。。

    字符串hash(模板)

    http://blog.csdn.net/gdujian0119/article/details/6777239

    BKDR Hash Function  :

    // BKDR Hash Function  
    unsigned int BKDRHash(char *str)  
    {  
        unsigned int seed = 131; // 31 131 1313 13131 131313 etc..  
        unsigned int hash = 0;  
       
        while (*str)  
        {  
            hash = hash * seed + (*str++);  
        }  
       
        return (hash & 0x7FFFFFFF);  
    }  

    本题hash解法 n^2

    #define ULL unsigned long long
    const int maxn = 5111 * 2;
    
    const int HASH = 10007;
    struct HashMap{
        int head[HASH];
    
        int next[maxn];
        ULL state[maxn];
        int num_s1[maxn];
        int num_s2[maxn];
    
        int sz;
        void init()
        {
            sz = 0;
            memset(head, -1, sizeof(head));
        }
        int insert(ULL val, bool info)
        {
            int h = val % HASH;
            for (int i = head[h]; i != -1; i = next[i])
            {
                if (val == state[i])
                {
                    if (info) num_s1[i]++;
                    else num_s2[i]++;
                    return 1;///存在
                }
            }
            num_s1[sz] = 0;
            num_s2[sz] = 0;
            state[sz] = val;
            next[sz] = head[h];
    
            if (info) num_s1[sz]++;
            else num_s2[sz]++;
    
            head[h] = sz++;
    
            return 0;///不存在
        }
        bool check()
        {
            for (int i = 0; i < sz; i++)
            {
                if (num_s1[i] == num_s2[i] && num_s1[i] == 1)
                    return true;
            }
            return false;
        }
    }H;
    
    
    const int SEED = 13331;
    ULL P[maxn];
    ULL s1[maxn], s2[maxn];
    
    char sa[maxn], sb[maxn];
    
    void hash_pre(ULL P[])
    {
        P[0] = 1;
        for (int i = 1; i <= maxn; i++)
        P[i] = P[i - 1] * SEED;
    }
    void hash_init(ULL s1[], char sa[])///sa[],下标从0開始;相应是s1[]的值得下标从1開始
    {
        int n = strlen(sa);
        s1[0] = 0;
        for (int i = 1; i <= n; i++)
            s1[i] = s1[i - 1] * SEED + sa[i - 1];
    }
    ULL getSeg(ULL s1[], int l, int r)///求s1[]的下标区间的hash值
    {
        return s1[r] - s1[l - 1] * P[r - l + 1];
    }
    
    int main()
    {
        hash_pre(P);
    
        RS(sa); RS(sb);
        int n = strlen(sa), m = strlen(sb);
    
        hash_init(s1, sa);
        hash_init(s2, sb);
    
        int fla = 0;
        int mn = min(n, m);
        for (int i = 1; i <= mn; i++)
        {
            H.init();
            for (int j = i; j <= n; j++)
            {
                H.insert(getSeg(s1, j - i + 1, j), 0);
            }
            for (int j = i; j <= m; j++)
            {
                H.insert(getSeg(s2, j - i + 1, j), 1);
            }
    
            if (H.check())
            {
                printf("%d
    ", i);
                fla = 1;
                break;
            }
        }
        if (!fla) puts("-1");
        return 0;
    }
    


    后缀数组:


    const int MAXN = 5111 * 2;
    const int INF = 0x3f3f3f3f;
    int wa[MAXN], wb[MAXN], wv[MAXN], wn[MAXN];
    //char r[MAXN];
    int a[MAXN], sa[MAXN], rank[MAXN], height[MAXN];
    
    int cmp(int *r, int a,int b, int k)
    {
        return r[a] == r[b] && r[a + k] == r[b + k];
    }
    void build_sa(int *r, int *sa, int n,int m)
    {
       int i,j, p;
       int *x = wa, *y = wb, *t;
       for (int i= 0; i < m; i++) wn[i] = 0;
       for (int i= 0; i < n; i++) wn[x[i] = r[i]]++;
       for (int i = 1; i < m; i++) wn[i] += wn[i - 1];
       for (int i = n - 1; i >= 0; i--) sa[--wn[x[i]]] = i;
       for (p = 1, j = 1; p < n; j <<= 1, m = p)
       {
           for (p = 0, i = n - j; i < n; i++) y[p++] = i;
           for (i = 0; i < n; i++) if (sa[i] >= j) y[p++] = sa[i] - j;
    
           for (i = 0; i < m; i++) wn[i] = 0;
           for (i = 0; i < n; i++) wn[wv[i] = x[y[i]]]++;
           for (i = 1; i < m; i++) wn[i] += wn[i - 1];
           for (i = n - 1; i >= 0; i--) sa[--wn[wv[i]]] = y[i];
    
           t = x; x = y; y = t;
           x[sa[0]] = 0; p = 1;
           for (i = 1; i < n; i++)
                x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++;
       }
    }
    void getHeight(int *r, int *sa, int n)
    {
        int i, j, k = 0;
        for (i = 1; i <= n; i++)
        {
            rank[sa[i]] = i;
            height[i] = 0;
        }
        for (i = 0;i < n; i++)
        {
            if (k) k--;
            j = sa[rank[i] - 1];
            while (r[i + k] == r[j + k]) k++;
            height[rank[i]] = k;
        }
    }
    
    
    char ca[MAXN], cb[MAXN];
    
    void solve(int n)
    {
        height[n + 1] = 0;
        int ans = INF;
        int l = strlen(ca);
        for (int i = 1; i <= n; i++)
        {
            if (!height[i]) continue;
            if (sa[i] < l && sa[i - 1] < l) continue;
            if (sa[i] >= l && sa[i - 1] >= l) continue;
            int pre = height[i - 1] + 1;
            int next = height[i + 1] + 1;
            if (height[i] >= max(pre, next))
            {
                ans = min(ans, max(pre, next));
            }
        }
        if (ans == INF) puts("-1");
        else printf("%d
    ", ans);
    }
    int main()
    {
        int t, n, m;
    
        ///n, m
        n = 0;
        m = 256;
    
        RS(ca);
        int l = strlen(ca);
        REP(j, l) a[n++] = (int)ca[j];
        a[n++] = m++;
    
        RS(cb);
        l = strlen(cb);
        REP(j, l) a[n++] = (int)cb[j];
        a[n++] = m++;
    
        a[--n] = 0; --m;
    
        build_sa(a, sa, n + 1, m);
        getHeight(a, sa, n);
    
        solve(n);
    
        return 0;
    }
    /*
    0 8 0
    1 6 0
    2 4 2
    3 2 4
    4 0 6
    5 7 0
    6 5 1
    7 3 3
    8 1 5
    ^^^^^^^^^^^^^^
    
    0 4
    1 8
    2 3
    3 7
    4 2
    5 6
    6 1
    7 5
    8 0
    ^^^^^^^^^^^^^^
    */
    



  • 相关阅读:
    C#调试信息打印到输出窗口
    C#拼接SQL中in条件
    从图像到知识:深度神经网络实现图像理解的原理解析
    Cocoa Touch(六):App运行机制 NSRunLoop, KVC, KVO, Notification, ARC
    Cocoa Touch(五):网络请求 NSURLSession/AFNetworking, GCD, NSURLResquest
    JQuery:选择器、动画、AJAX请求
    Cocoa Touch(四): 多线程GCD, NSObject, NSThread, NSOperationQueue
    Socket、RPC通信实例,简单版本,仅供查阅
    Cocoa Touch(三):图形界面UIKit、Core Animation、Core Graphics
    Cocoa Touch(二):数据存储CoreData, NSKeyArchiver, NSOutputStream, NSUserDefaults
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5371894.html
Copyright © 2011-2022 走看看