zoukankan      html  css  js  c++  java
  • hdu6138 hash+二分

    题意: n个串,每次查询两个,问最长的公共自串并且这个子串要是n个串其中一个的前缀。


    思路:正解是AC自动机。。。这里瞎搞了一下居然过了,直接二分答案,然后判断(类似hash求公共子串一样),就再加一个是不是前缀的判断就好。。

    时间复杂度理论上最差n*m*logn。。。但是神奇的只跑了150ms。。。


    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define MEM(a,b) memset(a,b,sizeof(a))
    #define bug puts("bug");
    #define PB push_back
    #define MP make_pair
    #define X first
    #define Y second
    typedef unsigned long long ll;
    typedef pair<int,int> pii;
    const int maxn=1e5+10;
    const int mod=1e9+7;
    using namespace std;
    int t,m,n,k;
    string s[maxn];
    const unsigned long long SEED = 13331;
    unsigned long long P[maxn],S[maxn];
    unsigned long long HS(int l,int r,int x){
        if(l==r) return s[x][l-1];
        return S[r] - S[l-1]*P[r-l+1];
    }
    unordered_set<unsigned long long> st,tmp;
    bool ok(int len,int x,int y){
        tmp.clear();
        for(int i=1;i<=s[x].size();i++)
            S[i] = S[i-1]*SEED + s[x][i-1];
        for(int i=1;i+len-1<=s[x].size();i++)
            tmp.insert(HS(i,i+len-1,x));
        for(int i=1;i<=s[y].size();i++)
            S[i] = S[i-1]*SEED + s[y][i-1];
        for(int i=1;i+len-1<=s[y].size();i++)
            if(tmp.count(HS(i,i+len-1,y))&&st.count(HS(i,i+len-1,y)))
                return true;
        return false;
    }
    
    int main(){
        P[0] = 1;S[0]=0;
        for(int i = 1; i < maxn; i++)P[i] = P[i-1] * SEED;
        ios::sync_with_stdio(false);
        cin>>t;
        while(t--){
            st.clear();
            cin>>n;
            for(int i=0;i<n;i++) cin>>s[i];
            for(int i=0;i<n;i++)
                for(int j=1;j<=s[i].size();j++)
                    S[j] = S[j-1]*SEED + s[i][j-1],st.insert(S[j]);
            cin>>m;
            int x,y;
            for(int i=0;i<m;i++){
                cin>>x>>y;
                --x;--y;
                int l=0,r=min(s[x].size(),s[y].size());
                while(l<=r){
                    int mid=(l+r)/2;
                    if(ok(mid,x,y)) l=mid+1;
                    else r=mid-1;
                }
                cout<<r<<endl;
            }
        }
        return 0;
    }
    


  • 相关阅读:
    最近学习下,nohup和&的区别
    java 关键字
    iOS之事件穿透
    排序算法——快速排序
    分布式-选举算法
    分布式选举算法
    SolrCloud 分布式集群部署步骤
    linux 启动两个tomcat
    solr安装-tomcat+solrCloud构建稳健solr集群
    JAVA 中BIO,NIO,AIO的理解
  • 原文地址:https://www.cnblogs.com/zhangxianlong/p/10672497.html
Copyright © 2011-2022 走看看